This notebook is part of an exploratory analysis of machine learning used to decompose hyperspectral datasets of hybrid perovskite nanoscale materials.

Two machine learning models are mainly used in this project: Nonnegative Matrix Factorization (NMF) and Variational Autoencoders (VAEs). This notebook implements semi-supervised VAE models to better represent the types of spectral features and their locations in the material.

Notebook Four: Semi-Supervised VAE

Imports, Functions, and Classes¶

Imports¶

InĀ [1]:
from preprocessing import *

import torch
from torchvision.utils import make_grid
import pyroved as pv
import pyro.distributions as dist
import pyro
from pyroved.models.base import baseVAE
from pyroved.nets import fcDecoderNet, fcEncoderNet, sDecoderNet
from pyroved.utils import (
    generate_grid, get_sampler, set_deterministic_mode, to_onehot, transform_coordinates)

save_directory = "./png-figures/" # modify to save figures as a specified file extension
file_extension = ".png"
SEM images: f1_img1, f2_img1
CL images: f1_img2, f2_img2
Denoised data: f1_sb_median, f2_sb_median
2D denoised data: f1_denoised_2d, f2_denoised_2d
Example points: f1_x_points, f1_y_points, f2_x_points, f2_y_points
Wavelengths and dimensions: f1_wav, f2_wav, f1_xpix, f1_ypix, f1_zpix, f2_xpix, f2_ypix, f2_zpix

Unsupervised Variational Autoencoder¶

An autoencoder is an unsupervised neural network model that learns two functions: an encoding function (transforms input into latent space representation with lower dimensionality) and a decoding function (recreates input data from latent representation). The autoencoder attempts to optimize the representation of unbalanced/non-linear data (as opposed to PCA or NMF, which are linear). It is more deterministic in its approach than a VAE.

Hyperparameters: Code size, number of layers, number of nodes per layer, and the loss function

Architecture: Input, encoder, latent space, decoder, and output

A variational autoencoder is a generative, semi-supervised autoencoder with the addition of regularized training (which prevents overfitting). This crucial additional step allows for each point in the latent space to yield meaningful data, allowing for generative processes. These are more probabilistic in nature and enforce a (generally Gaussian) distribution in the sampling process. The end result is a latent space that is optimized for clustering together similar data points while giving a continuous distribution across the entire latent space. This is achieved through minimizing the KL divergence (causing the mean to approach 0 and the standard deviation to approach 1).

VAE%20architecture%20%28white%20BG%29.png

Loss function: reconstruction term (Gradient descent) (makes encoding and decoding efficient) + regularization term (Kullback-Leibler Divergence) (creates regular latent space)

VAEs use a "reparameterization trick" to allow for backpropagation, which is impossible through a stochastic node. The process of sampling from a distribution that is parameterized by the model is not differentiable, and this is a problem for gradient-based approaches. There must be a method of making the predictions separate from the stochastic sampling element.

It accomplishes this by treating random sampling as a noise term which is now independent and not parameterized by the model. A Gaussian can be scaled by a sample from the noise distribution multiplied by the standard deviation added to the mean. This allows for further differentiation through the model.

We are primarily interested in the latent space representation of the data as this reveals to us the correlations in the data that the model detects. However many latent dimensions we specify in the training will be the number of principal components we analyze and their correlations to one another.

Semi-supervised machine learning involves aspects of both supervised and unsupervisded machine learning. A small portion of the training data is labeled, and this is used to classify the majority of the data, which is unlabeled. The goal here is to label several spectral features within the data and asses how well the model is able to pick up on the locations of these features through training in order to predict their location in new data.

Plot Code¶

vae_plot builds a plot of the latent space dimensions with two or three latent dimensions and plots points corresponding to single pixels in the x and y axes of the original dataset. The point is to show a relationship between different spectral features detected by the autoencoder. Below the plot is an image component of the latent representation of the data.

spectra_plot plots each spectrum in the image color mapped according to its value along a specified axis.

ssvae_plot plots the latent space and image reconstruction of SSVAE models

pointfinder_plot shows every spectrum with a certain x value (along a vertical line in the image).

spectsig_plot shows all labeled spectra color mapped according to each class

ssvae_label_plot shows the first 180 spectra the SSVAE model assigns to a specified class

spect_label_plot plot one spectrum from each class in the labeled data

custom_spect_label_plot plot one spectrum from each class in the latent representation of the data

InĀ [Ā ]:
# Plotting pixels containing entire spectra in a latent space and corresponding images
def vae_plot(suptitle, z_mean, xpix, ypix, scalebar_size, save=False):
    
    rows = 2
    columns = len(z_mean[0])
    
    fig = plt.figure(figsize=(4,4))
    fig.suptitle(suptitle, fontsize=10)
    fig.patch.set_facecolor("white")
    
    for i in range(rows):
        for j in range(columns):
            
            if i == 0: # First row
                
                if columns == 2: # 2D Latent space
                    ax = fig.add_subplot(2, 2, j + 1)
                    ax.scatter(z_mean[:, 0], z_mean[:, 1], c=z_mean[:, j], cmap=cmap,
                            ec='black', lw=0.1, alpha=0.6, s=2)
                    ax.tick_params(axis='both', which='major', labelsize=4, direction='out', 
                               length=2, width=0.5)
                    
                else: # 3D Latent space
                    ax = fig.add_subplot(2, 3, j + 1, projection='3d')
                    ax.scatter(z_mean[:, 0], z_mean[:, 1], z_mean[:, 2], 
                            c=z_mean[:, j], cmap=cmap,
                            ec='black', lw=0.05, alpha=0.5, s=2)
                    ax.set_xticklabels([])
                    ax.set_yticklabels([])
                    ax.zaxis.set_ticklabels([])
                    ax.set_xlabel("X", size=5, labelpad=-15)
                    ax.set_ylabel("Y", size=5, labelpad=-15)
                    ax.set_zlabel("Z", size=5, labelpad=-15)
                    if j == 0:
                        ax.view_init(30, -85) 
                    elif j == 1:
                        ax.view_init(30, -40)
                    elif j == 2:
                        ax.view_init(30, 5)
                
                if j == 0:
                    ax.set_title('Latent Space', size=7)
            
            if i == 1: # Second row
                
                if columns == 2: # 2D Latent Space
                    img = fig.add_subplot(2, 2, j+3)
                else: # 3D Latent Space
                    img = fig.add_subplot(2, 3, j+4)
                    
                img.imshow(z_mean[:,j].reshape(ypix, xpix), cmap=cmap)
                img.set_xticks([])
                img.set_yticks([])
                
                if j == (columns-1): # Add scalebar to bottom right image
                    scalebar = AnchoredSizeBar(img.transData, scalebar_size, " ", 
                            "lower right", pad=0.2, color='#F2F2F2', frameon=False,
                                               size_vertical=3, label_top=True)
                    img.add_artist(scalebar)
    
    if save:
        fig.savefig(save_directory + "unsupervised-vae/" + suptitle + file_extension)
        
# Spectra Plot (for determining latent dimensions)
def spectra_plot(suptitle, img, array, xpix, ypix, wav, save=False):
    
    n = xpix*ypix # total number of spectra
    cmap = mpl.colormaps['viridis'](np.linspace(0,1,n)) # create colormap
    fig = plt.figure(figsize=(6,3))
    fig.suptitle(suptitle, fontsize=10)
    fig.patch.set_facecolor('white')
    ax = fig.add_subplot()
    ax.set_prop_cycle('color', list(cmap)) # colormaps each spectra from first to last in array
    ax.tick_params(axis='both', which='major', labelsize=5, direction='out', length=2, width=0.5)
    plt.xlim(short_wav - 5, long_wav + 5)
    #ax.set_xticks([500, 750])
    #ax.set_xticklabels([])
    #plt.yscale('log')
    
    for i in array:
        ax.plot(wav, img[:,i[0],i[1]], lw=0.03, alpha=0.5)
    
    if save:
        fig.savefig(save_directory + "unsupervised-vae/" + suptitle + file_extension)

        
# SEMI-SUPERVISED VAE

# Plot the latent space and image reconstruction of SSVAE models
def ssvae_plot(suptitle, z_mean, z_labels, xpix, ypix, scalebar_size, save=False):
    
    rows = 2
    columns = 1
    
    cmap = mpl.colormaps['viridis']
    fig = plt.figure(figsize=(4,4))
    fig.suptitle(suptitle, fontsize=10)
    gs = GridSpec(rows, columns)
    #fig.patch.set_facecolor('#00000000')
    fig.patch.set_facecolor('white')
    
    for i in range(rows):
        column_count = 0
        for j in range(columns):
            if i == 0:
                ax = fig.add_subplot(gs[0,column_count])
                ax.scatter(z_mean[:,0], z_mean[:,1], c=z_labels, cmap=cmap,
                        ec='black', lw=0.05, alpha=0.6, s=2)
                #ax.tick_params(axis='both', labelsize=10)
                ax.set_xticks([])
                ax.set_yticks([])
                
            if i == 1:
                img = fig.add_subplot(gs[1,column_count])
                img.imshow(z_labels.reshape(ypix, xpix), cmap=cmap)
                img.set_xticks([])
                img.set_yticks([])
                
                if column_count == (columns-1):
                    scalebar = AnchoredSizeBar(img.transData, scalebar_size, " ", 
                            "lower right", pad=0.3, color='#F2F2F2', frameon=False,
                                               size_vertical=3, label_top=True)
                    img.add_artist(scalebar)

            column_count += 1
    
    if save:
        fig.savefig(save_directory + "semi-supervised-vae/" + suptitle + file_extension)

# Function to plot every spectrum with a certain x value (along a vertical line in the image)
def pointfinder_plot(img, x_pt, ypix, wav):
    
    rows = ypix
    columns = 1
    fig = plt.figure(figsize=(4, rows))
    
    for i in range(rows):

        ax = fig.add_subplot(rows, columns, i + 1)
        ax.plot(wav, img[:, i, x_pt], c=color[i], lw=2)
        ax.text(220, 350, str([i, x_pt]), fontsize=5)
        ax.set_xticks([])
        ax.set_yticks([])   

    plt.show()

# Plot all spectra in each of the 4 classes
def spectsig_plot(suptitle, img, pts, wav, save=False):
    
    rows = len(pts[0])
    columns = 4
    gs = GridSpec(rows, columns)
    gs.update(wspace=0, hspace=0)

    figsize = (columns*2, rows)
    fig = plt.figure(figsize=figsize)
    fig.patch.set_facecolor("white")
    fig.suptitle(suptitle, fontsize=20)
    #fig.subplots_adjust(top=0.95, bottom=0.1)

    row_count = 0
    for i in range(rows):

        column_count = 0
        for j in range(columns):

            fig_plt = fig.add_subplot(gs[i,j])
            fig_plt.plot(wav, img[pts[j][i][0],pts[j]
                                  [i][1],:], c=cmap_list[j], lw=1)
            plt.xlim(short_wav - 5, long_wav + 5) # Cropping the spectra shown in the plot
            #fig_plt.tick_params(axis='both', direction='out', length=12, width=4)
            fig_plt.set_xticks([])
            fig_plt.set_yticks([])
            
            #if column_count == 0:
                #fig_plt.set_yticks([1000])
                #fig_plt.set_yticklabels([])
                #fig_plt.tick_params(axis='y', direction='out', length=12, width=4)
            
            #if row_count == rows-1:
                #fig_plt.set_xticks([400-short_wav, 750-long_wav])
                #fig_plt.set_xticklabels([])
                #fig_plt.tick_params(axis='x', direction='out', length=12, width=4)

            column_count += 1

        row_count += 1
    
    if save:
        fig.savefig(save_directory + "semi-supervised-vae/" + suptitle + file_extension)
    plt.show()
    
# This plot shows the first 180 spectra the SSVAE model assigns to a specified class
def ssvae_label_plot(img, pts, wav, starting_index=0, save=False):
    
    rows = 180
    #rows = len(pts)
    columns = 1
    fig = plt.figure(figsize=(4, rows))
    fig.patch.set_facecolor("white")
    #fig.suptitle(suptitle, fontsize=30)
    gs = GridSpec(rows, columns)
    
    row_count = 0
    for i in range(starting_index, starting_index + rows):

        fig_plt = fig.add_subplot(gs[row_count,0])
        fig_plt.plot(wav, img[:, pts[i,0], pts[i,1]], 
                     c=color[row_count], lw=3)
        plt.xticks([])
        plt.yticks([])
        #plt.text(220,350,str((int(pts[i][0]),int(pts[i][1]))))
        plt.text(0, 0, str(i))
        row_count += 1

    #gs.tight_layout(fig, rect=[0,0.03,1,0.95])
    if save:
        fig.savefig(save_directory + "semi-supervised-vae/" + suptitle + file_extension)
    plt.show()

# Plot one spectrum from each class in the labeled data
def spect_label_plot(suptitle, img, pts, wav, save=False):
    
    rows = 1
    columns = 4
    gs = GridSpec(rows, columns)
    gs.update(wspace=0,hspace=0.2)

    figsize = (columns*4, rows*3)
    fig = plt.figure(figsize=figsize)
    fig.suptitle(suptitle, size = 20)
    fig.patch.set_facecolor("white")
    #fig.patch.set_facecolor('#00000000')
    #fig.suptitle(suptitle, fontsize=30)
    #fig.subplots_adjust(top=0.95, bottom=0.1)

    row_count = 0
    for i in range(rows):

        column_count = 0
        for j in range(columns):

            fig_plt = fig.add_subplot(gs[i,j])
            fig_plt.plot(wav, img[:,pts[j][i][0],pts[j][i][1]], c=cmap_list[j], lw=3)
            #plt.text(300, 370, str(column_count))
            #fig_plt.set_title(method_names[row_count] + point_names[column_count])
            #fig_plt.tick_params(color=color[j])
            plt.xlim(short_wav - 5, long_wav + 5) # Cropping the spectra shown in the plot
            #fig_plt.tick_params(axis='both', direction='out', length=12, width=4)
            #fig_plt.set_xticks([400, 550, 750])
            fig_plt.set_yticks([])
            fig_plt.set_xticks([])

            column_count += 1

        row_count += 1
    
    if save:
        fig.savefig(save_directory + "/semi-supervised-vae/" + suptitle + file_extension)
    plt.show()

# Plot one spectrum from each class in the latent representation of the data
def custom_spect_label_plot(suptitle, img, pts, wav, save=False):
    
    rows = 1
    columns = 4
    gs = GridSpec(rows, columns)
    gs.update(wspace=0,hspace=0.2)

    figsize = (columns*4, rows*3)
    fig = plt.figure(figsize=figsize)
    #fig.patch.set_facecolor("#00000000")
    fig.patch.set_facecolor("white")
    fig.suptitle(suptitle, fontsize=20)
    #fig.subplots_adjust(top=0.95, bottom=0.1)

    row_count = 0
    for i in range(rows):

        column_count = 0
        for j in range(columns):

            fig_plt = fig.add_subplot(gs[i, j])
            fig_plt.plot(wav, img[:, pts[j][0], pts[j][1]], c=cmap_list[j], lw=3)
            #plt.text(300, 370, str(column_count))
            #fig_plt.set_title(method_names[row_count] + point_names[column_count])
            #fig_plt.tick_params(color=color[j])
            plt.xlim(short_wav, long_wav) # Cropping the spectra shown in the plot
            fig_plt.tick_params(axis='both', direction='out', length=6, width=2)
            #fig_plt.set_xticks([400, 750])
            fig_plt.set_xticks([])
            fig_plt.set_yticks([])
            #fig_plt.set_xticklabels([])
            
            #if column_count == 0:
                #fig_plt.set_yticks([1000])
                #fig_plt.set_yticklabels([])
                #fig_plt.tick_params(axis='y', direction='out', length=12, width=4)
            
            #if row_count == rows-1:
                #fig_plt.set_xticks([400-short_wav, 750-long_wav])
                #fig_plt.set_xticklabels([])
                #fig_plt.tick_params(axis='x', direction='out', length=12, width=4)

            column_count += 1

        row_count += 1
    
    if save:
        fig.savefig(save_directory + "/semi-supervised-vae/" + suptitle + file_extension)
    plt.show()

Invariant VAE (2 latent dimensions)¶

Variational autoencoder that enforces rotational, translational, and scale invariances. The goal is to remove any effect these transformations will cause in the encoding process and to pick up on the similarities in the features.

Grain 1¶

Code¶

First step: Transpose denoised array, reshape to 1D, normalize entire dataset, and reshape to 2D

Second step: Convert from Numpy array to PyTorch tensor, then find number of samples (spectra) and signal (number of points in image along x and y axes containing spectra)

(pv.utils.init_dataloader: Returns initialized PyTorch dataloader, which is used by pyroVED’s trainers. The inputs are torch Tensor objects containing training data and, optionally, labels.)

Third step: Create a dataloader object with unsqueezed training data. This is the entire hyperspectral array reshaped into 2 dimensions with another dimension of size one inserted into the array

(pyroved.trainers.SVItrainer: Stochastic variational inference (SVI) trainer for unsupervised and class-conditioned VED models consisting of one encoder and one decoder.)

Fourth step: An invariant VAE model with 2 latent dimensions is created along with an SVI trainer. Then, 50 epochs are run with every 10 epochs printing the training loss, showing the convergence to local minima.

Fifth step: pv.models.iVAE.encode returns the mean and standard deviation of the Z (latent) space, giving an array of image points (20008 for Figure 1), each containing an entire spectrum, plotted on an axis of specified latent dimensions (in this case, 2)

InĀ [3]:
# Reshaping the 2D array to 1D. Imagine the 3D hyperspectral image, take the top left pixel's (from the perspective of the x-y plane)
# spectrum, add the spectrum of the pixel to the right to the end, and continue left to right, top to bottom, until the entire image is 1D.
f1_denoised_1d_transpose = f1_denoised_2d.transpose(1,0).reshape(f1_zpix*f1_ypix*f1_xpix)
# Normalize the entire 1D array, then reshape it to 2D, pixels by spectra, arranged left to right and top to bottom
f1_denoised_2d_norm = normalize(f1_denoised_1d_transpose).reshape(f1_xpix*f1_ypix, f1_zpix)
# Convert to Torch tensor object
f1_denoised_2d_norm_t = torch.from_numpy(np.array(f1_denoised_2d_norm).astype('float64')).float()
f1_n_samples = f1_denoised_2d_norm_t.size()[0] # number of spectral points
f1_l_signal = f1_denoised_2d_norm_t.size()[1] # number of spectra

f1_train_data = f1_denoised_2d_norm_t.clone()
f1_train_loader = pv.utils.init_dataloader(f1_train_data.unsqueeze(1), batch_size=64)

f1_in_dim = (f1_l_signal,)
# Gradually increase the weight of the KL Divergence term in the loss function with each epoch
f1_kl_scale = torch.linspace(start=.001, end=.01, steps=50)

# Training the model
f1_vae = pv.models.iVAE(f1_in_dim, latent_dim=2, invariances=None, sampler_d="gaussian")
f1_vae_trainer = pv.trainers.SVItrainer(f1_vae)

for e in range(50):
    sc = f1_kl_scale[e] if e < len(f1_kl_scale) else f1_kl_scale[-1]
    f1_vae_trainer.step(f1_train_loader, scale_factor=sc)
    if e//10 == e/10:
        f1_vae_trainer.print_statistics()
        
f1_vae_z_mean, f1_vae_z_sd = f1_vae.encode(f1_train_data)

f1_vae_z_mean = normalize(f1_vae_z_mean)
f1_vae_z_sd = normalize(f1_vae_z_sd)
Epoch: 1 Training loss: 157.6064
Epoch: 11 Training loss: 145.6802
Epoch: 21 Training loss: 145.6788
Epoch: 31 Training loss: 145.6842
Epoch: 41 Training loss: 145.6906
InĀ [10]:
vae_plot("Vanilla VAE Grain 1", f1_vae_z_mean, f1_xpix, f1_ypix, 50)
No description has been provided for this image

Grain 2¶

Code¶

InĀ [5]:
f2_denoised_1d_transpose = f2_denoised_2d.transpose(1,0).reshape(f2_zpix*f2_ypix*f2_xpix)
f2_denoised_2d_norm = normalize(f2_denoised_1d_transpose).reshape(f2_ypix*f2_xpix, f2_zpix)
    
f2_denoised_2d_norm_t = torch.from_numpy(np.array(f2_denoised_2d_norm).astype('float64')).float()

f2_n_samples = f2_denoised_2d_norm_t.size()[0] # number of spectra
f2_l_signal = f2_denoised_2d_norm_t.size()[1] # number of spectral points

f2_train_data = f2_denoised_2d_norm_t.clone()
f2_train_loader = pv.utils.init_dataloader(f2_train_data.unsqueeze(1), batch_size=64)

f2_in_dim = (f2_l_signal,)
f2_kl_scale = torch.linspace(.001, .01, 50)

# Training the model
f2_vae = pv.models.iVAE(f2_in_dim, latent_dim=2, invariances=None, sampler_d="gaussian")
f2_vae_trainer = pv.trainers.SVItrainer(f2_vae)

for e in range(50):
    sc = f2_kl_scale[e] if e < len(f2_kl_scale) else f2_kl_scale[-1]
    f2_vae_trainer.step(f2_train_loader, scale_factor=sc)
    if e//10 == e/10:
        f2_vae_trainer.print_statistics()
        
f2_vae_z_mean, f2_vae_z_sd = f2_vae.encode(f2_denoised_2d_norm_t)

f2_vae_z_mean = normalize(f2_vae_z_mean)
f2_vae_z_sd = normalize(f2_vae_z_sd)
Epoch: 1 Training loss: 179.1582
Epoch: 11 Training loss: 145.7374
Epoch: 21 Training loss: 145.7132
Epoch: 31 Training loss: 145.7104
Epoch: 41 Training loss: 145.6995
InĀ [11]:
vae_plot("Vanilla VAE Grain 2", f2_vae_z_mean, f2_xpix, f2_ypix, 33.333333333)
No description has been provided for this image

Semi-Supervised VAE on Grain 1¶

Semi-supervised machine learning involves aspects of both supervised and unsupervisded machine learning. A small portion of the training data is labeled, and this is used to classify the majority of the data, which is unlabeled. The goal here is to label several spectral features within the data and asses how well the model is able to pick up on the locations of these features through training in order to predict their location in new data.

Preparing Data¶

Plot spectral signature classes¶

First, manually determine 6 examples of each of the 4 features present in the material, giving a labeled set of 24 spectra

InĀ [38]:
pointfinder_plot(f1_img2, 9, f1_ypix, f1_wav)
No description has been provided for this image
InĀ [37]:
# arrays of points labeled 0 to 3, totalling 4 classes
# format: [y, x]
f1_pts0 = [[50,50], [40,23], [40,21], [113,69], [93,75], [80,73], [4,4], [1,5], [55,100], [42,92]]
f1_pts1 = [[65,10], [67,17], [68,17], [69,17], [70,17], [74,17], [53,7], [52,7], [54,7], [74,9]]
f1_pts2 = [[22,142], [95,72], [96,72], [96,73], [95,71], [9,65], [47,8], [45,7], [43,7], [48,8]]
f1_pts3 = [[89,53], [9,67], [72,9], [7,69], [95,69], [7,72], [46,4], [42,4], [55,7], [42,8]]
f1_pts = [f1_pts0, f1_pts1, f1_pts2, f1_pts3]

# Reshape normalized 2D data to 3D
f1_denoised_3d_norm_t = f1_denoised_2d_norm_t.reshape(f1_ypix, f1_xpix, f1_zpix)
# Reshape denoided 2D data to 3D
f1_denoised_3d = np.reshape(f1_sb_median, (f1_zpix, f1_ypix, f1_xpix), order='C')
InĀ [45]:
spectsig_plot("Four Classes of Spectral Features", f1_denoised_3d_norm_t, f1_pts, f1_wav)
No description has been provided for this image

Modeling Data¶

X_sup: 16 labeled spectra for supervised training

y_sup: one-hot labels for the spectra (tensor of same size as X_sup)

X_val: 8 labeled spectra for validation step

y_val: labels for validation step

X_unsup: the rest of the spectra, with the above spectra replaced with zeros

InĀ [47]:
# Create normalized, denoised, hyperspectral image
f1_denoised_3d_norm = normalize(f1_denoised_1d_transpose).reshape(f1_ypix, f1_xpix, f1_zpix)

# Labeled data
n_samples = len(f1_pts0)
n_sup = n_samples - 3 # number of supervised samples
n_val = 3 # number of validation samples
f1_X_sup = torch.stack((f1_denoised_3d_norm_t[f1_pts0[0][0],f1_pts0[0][1],:], 
                    f1_denoised_3d_norm_t[f1_pts0[1][0],f1_pts0[1][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[2][0],f1_pts0[2][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[3][0],f1_pts0[3][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[4][0],f1_pts0[4][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[5][0],f1_pts0[5][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[6][0],f1_pts0[6][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[0][0],f1_pts1[0][1],:], 
                    f1_denoised_3d_norm_t[f1_pts1[1][0],f1_pts1[1][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[2][0],f1_pts1[2][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[3][0],f1_pts1[3][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[4][0],f1_pts1[4][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[5][0],f1_pts1[5][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[6][0],f1_pts1[6][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[0][0],f1_pts2[0][1],:], 
                    f1_denoised_3d_norm_t[f1_pts2[1][0],f1_pts2[1][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[2][0],f1_pts2[2][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[3][0],f1_pts2[3][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[4][0],f1_pts2[4][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[5][0],f1_pts2[5][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[6][0],f1_pts2[6][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[0][0],f1_pts3[0][1],:], 
                    f1_denoised_3d_norm_t[f1_pts3[1][0],f1_pts3[1][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[2][0],f1_pts3[2][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[3][0],f1_pts3[3][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[4][0],f1_pts3[4][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[5][0],f1_pts3[5][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[6][0],f1_pts3[6][1],:])).float()

f1_sup_labels = torch.cat([torch.zeros(n_sup), torch.ones(n_sup),
                           2*torch.ones(n_sup), 3*torch.ones(n_sup)])
f1_y_sup = pv.utils.to_onehot(f1_sup_labels.long(), n=4) # create onehot array for supervised labels

f1_X_val = torch.stack((f1_denoised_3d_norm_t[f1_pts0[7][0],f1_pts0[7][1],:], 
                    f1_denoised_3d_norm_t[f1_pts0[8][0],f1_pts0[8][1],:],
                    f1_denoised_3d_norm_t[f1_pts0[9][0],f1_pts0[8][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[7][0],f1_pts1[7][1],:], 
                    f1_denoised_3d_norm_t[f1_pts1[8][0],f1_pts1[8][1],:],
                    f1_denoised_3d_norm_t[f1_pts1[9][0],f1_pts1[9][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[7][0],f1_pts2[7][1],:], 
                    f1_denoised_3d_norm_t[f1_pts2[8][0],f1_pts2[8][1],:],
                    f1_denoised_3d_norm_t[f1_pts2[9][0],f1_pts2[9][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[7][0],f1_pts3[7][1],:], 
                    f1_denoised_3d_norm_t[f1_pts3[8][0],f1_pts3[8][1],:],
                    f1_denoised_3d_norm_t[f1_pts3[9][0],f1_pts3[9][1],:])).float()

#f1_X_val = torch.cat(f1_X_val)
f1_val_labels = torch.cat([torch.zeros(n_val), torch.ones(n_val),
                           2*torch.ones(n_val), 3*torch.ones(n_val)])
f1_y_val = pv.utils.to_onehot(f1_val_labels.long(), n=4) # create onehot array for validation labels

# Remove all labeled samples from unlabeled data by setting them to zero
f1_X_unsup = f1_denoised_3d_norm_t
for i in range(n_samples):
    for j in range(4):
        f1_X_unsup[f1_pts[j][i][0], f1_pts[j][i][1], :] *= 0
        
f1_X_unsup = f1_X_unsup.reshape(f1_xpix*f1_ypix, f1_zpix)

# Randomly shuffle points in image
#f1_X_unsup = f1_X_unsup[torch.randperm(f1_X_unsup.size()[0])]

(f1_loader_unsup, f1_loader_sup,
 f1_loader_val) = pv.utils.init_ssvae_dataloaders(
     f1_X_unsup, (f1_X_sup, f1_y_sup), (f1_X_val, f1_y_val), batch_size=64)
r = (len(f1_X_sup) + len(f1_X_val)) / (len(f1_X_unsup))
print("Ratio of labeled data to unlabeled data: {}".format(r))
Ratio of labeled data to unlabeled data: 0.001999200319872051
InĀ [48]:
# Train the SSVAE model

f1_ss_data_dim = (f1_X_unsup.shape[1],)
latent_dim = 2
num_classes = 4 

# Initialize model
#f1_ssvae = pv.models.ss_reg_iVAE(
#    f1_ss_data_dim, latent_dim, num_classes, invariances=None)
f1_ssvae = pv.models.ssiVAE(
    f1_ss_data_dim, latent_dim, num_classes, invariances=None)

# Initialize trainer
f1_ss_trainer = pv.trainers.auxSVItrainer(f1_ssvae, task='classification')

# Gradually increase KL weight from 1 to 2 in the first 30 epochs
f1_ss_kl_scale = torch.linspace(1, 2, 30)
# Train model for n epochs
for e in range(50):
    sc = f1_ss_kl_scale[e] if e < len(f1_ss_kl_scale) else f1_ss_kl_scale[-1]
    f1_ss_trainer.step(f1_loader_unsup, f1_loader_sup, f1_loader_val,
                 aux_loss_multiplier=50, scale_factor=sc, sampler_d='gaussian')
    f1_ss_trainer.print_statistics()
    # Plot learned latent manifolds every 10 epoch
    #if (e+1) % 10 == 0:
        #plot_manifolds(f1_ssvae)
Epoch: 1 Training loss: 82.3200, Test accuracy: 0.2500
Epoch: 2 Training loss: 56.0877, Test accuracy: 0.2500
Epoch: 3 Training loss: 54.5155, Test accuracy: 0.2500
Epoch: 4 Training loss: 54.0529, Test accuracy: 0.3333
Epoch: 5 Training loss: 53.9958, Test accuracy: 0.2500
Epoch: 6 Training loss: 53.9822, Test accuracy: 0.3333
Epoch: 7 Training loss: 53.9917, Test accuracy: 0.3333
Epoch: 8 Training loss: 54.0051, Test accuracy: 0.3333
Epoch: 9 Training loss: 54.0207, Test accuracy: 0.3333
Epoch: 10 Training loss: 54.0421, Test accuracy: 0.3333
Epoch: 11 Training loss: 54.0690, Test accuracy: 0.3333
Epoch: 12 Training loss: 54.0930, Test accuracy: 0.3333
Epoch: 13 Training loss: 54.1123, Test accuracy: 0.2500
Epoch: 14 Training loss: 54.1381, Test accuracy: 0.2500
Epoch: 15 Training loss: 54.1642, Test accuracy: 0.3333
Epoch: 16 Training loss: 54.1878, Test accuracy: 0.3333
Epoch: 17 Training loss: 54.2150, Test accuracy: 0.3333
Epoch: 18 Training loss: 54.2338, Test accuracy: 0.3333
Epoch: 19 Training loss: 54.2592, Test accuracy: 0.3333
Epoch: 20 Training loss: 54.2802, Test accuracy: 0.3333
Epoch: 21 Training loss: 54.3063, Test accuracy: 0.3333
Epoch: 22 Training loss: 54.3245, Test accuracy: 0.3333
Epoch: 23 Training loss: 54.3407, Test accuracy: 0.3333
Epoch: 24 Training loss: 54.2891, Test accuracy: 0.3333
Epoch: 25 Training loss: 54.1891, Test accuracy: 0.3333
Epoch: 26 Training loss: 54.1486, Test accuracy: 0.3333
Epoch: 27 Training loss: 54.0379, Test accuracy: 0.3333
Epoch: 28 Training loss: 53.9685, Test accuracy: 0.3333
Epoch: 29 Training loss: 53.9524, Test accuracy: 0.3333
Epoch: 30 Training loss: 53.9416, Test accuracy: 0.3333
Epoch: 31 Training loss: 53.9302, Test accuracy: 0.3333
Epoch: 32 Training loss: 53.9260, Test accuracy: 0.3333
Epoch: 33 Training loss: 53.9220, Test accuracy: 0.3333
Epoch: 34 Training loss: 53.9255, Test accuracy: 0.3333
Epoch: 35 Training loss: 53.9218, Test accuracy: 0.3333
Epoch: 36 Training loss: 53.9196, Test accuracy: 0.3333
Epoch: 37 Training loss: 53.9266, Test accuracy: 0.3333
Epoch: 38 Training loss: 53.9149, Test accuracy: 0.3333
Epoch: 39 Training loss: 53.9187, Test accuracy: 0.3333
Epoch: 40 Training loss: 53.9155, Test accuracy: 0.3333
Epoch: 41 Training loss: 53.9236, Test accuracy: 0.3333
Epoch: 42 Training loss: 53.9145, Test accuracy: 0.3333
Epoch: 43 Training loss: 53.9206, Test accuracy: 0.3333
Epoch: 44 Training loss: 53.9099, Test accuracy: 0.3333
Epoch: 45 Training loss: 53.9234, Test accuracy: 0.3333
Epoch: 46 Training loss: 53.9131, Test accuracy: 0.3333
Epoch: 47 Training loss: 53.9183, Test accuracy: 0.3333
Epoch: 48 Training loss: 53.9132, Test accuracy: 0.3333
Epoch: 49 Training loss: 53.9174, Test accuracy: 0.3333
Epoch: 50 Training loss: 53.9123, Test accuracy: 0.3333
InĀ [49]:
#f1_ssvae.manifold2d(d=5, extent=[-5,5,-5,5])
#for i in range(2):
#    f1_ssvae.manifold_traversal(8, i, cmap='viridis')

f1_ssvae_z_mean, f1_ssvae_z_sd, f1_ssvae_z_labels = f1_ssvae.encode(f1_train_data)
f1_ssvae_z_mean = normalize(f1_ssvae_z_mean)
f1_ssvae_z_sd = normalize(f1_ssvae_z_sd)
f1_ssvae_z_labels_2d = f1_ssvae_z_labels.reshape(f1_ypix,f1_xpix)

Labels¶

InĀ [52]:
f1_ssvae_0_labels = (f1_ssvae_z_labels_2d == 0).nonzero(as_tuple=False)
f1_ssvae_1_labels = (f1_ssvae_z_labels_2d == 1).nonzero(as_tuple=False)
f1_ssvae_2_labels = (f1_ssvae_z_labels_2d == 2).nonzero(as_tuple=False)
f1_ssvae_3_labels = (f1_ssvae_z_labels_2d == 3).nonzero(as_tuple=False)

Label lists¶

InĀ [Ā ]:
print( len(f1_ssvae_0_labels),
      len(f1_ssvae_1_labels),
      len(f1_ssvae_2_labels),
      len(f1_ssvae_3_labels),
     len(f1_ssvae_0_labels)+len(f1_ssvae_1_labels)+len(f1_ssvae_2_labels)+len(f1_ssvae_3_labels))
InĀ [40]:
f1_ssvae_0_labels
Out[40]:
tensor([[  1,  80],
        [  1,  81],
        [  1,  86],
        ...,
        [104,  55],
        [113,   4],
        [113,   5]])
InĀ [41]:
f1_ssvae_1_labels
Out[41]:
tensor([[  0,  26],
        [  0,  27],
        [  0,  28],
        ...,
        [121, 161],
        [121, 162],
        [121, 163]])
InĀ [42]:
f1_ssvae_2_labels
Out[42]:
tensor([[  0,   0],
        [  0,   1],
        [  0,   2],
        ...,
        [121, 134],
        [121, 146],
        [121, 147]])
InĀ [43]:
f1_ssvae_3_labels
Out[43]:
tensor([[  0,  94],
        [  0,  95],
        [  1,   6],
        ...,
        [121,  88],
        [121, 112],
        [121, 113]])
InĀ [44]:
oh_no = 0
for i in f1_ssvae_0_labels:
    if i in f1_ssvae_1_labels:
        oh_no += 1
        
oh_no
Out[44]:
5531
InĀ [45]:
not_in = 0
what = []
for i in f1_ssvae_0_labels:
    if i in f1_ssvae_2_labels:
        not_in += 1
        what.append(i.tolist())
        
print(not_in, '\n')
print(what)
5531 

[[1, 80], [1, 81], [1, 86], [1, 87], [1, 95], [1, 96], [1, 97], [2, 29], [2, 30], [2, 31], [2, 32], [2, 44], [2, 46], [2, 47], [2, 48], [2, 49], [2, 51], [2, 58], [2, 59], [2, 60], [2, 61], [2, 62], [2, 63], [2, 68], [2, 69], [2, 73], [2, 74], [2, 75], [2, 76], [2, 77], [2, 78], [2, 79], [2, 80], [2, 81], [2, 82], [2, 83], [2, 95], [2, 96], [2, 97], [2, 98], [2, 99], [2, 100], [2, 101], [2, 102], [2, 103], [2, 104], [2, 154], [2, 155], [3, 29], [3, 30], [3, 31], [3, 32], [3, 33], [3, 34], [3, 35], [3, 36], [3, 37], [3, 38], [3, 39], [3, 40], [3, 43], [3, 44], [3, 45], [3, 46], [3, 47], [3, 48], [3, 52], [3, 53], [3, 54], [3, 55], [3, 56], [3, 57], [3, 58], [3, 59], [3, 60], [3, 61], [3, 62], [3, 63], [3, 64], [3, 65], [3, 66], [3, 67], [3, 68], [3, 69], [3, 70], [3, 71], [3, 72], [3, 73], [3, 74], [3, 75], [3, 76], [3, 77], [3, 78], [3, 98], [3, 99], [3, 100], [3, 101], [3, 102], [3, 103], [3, 104], [3, 111], [3, 112], [3, 113], [3, 114], [3, 115], [3, 150], [3, 151], [3, 152], [3, 153], [3, 154], [4, 23], [4, 24], [4, 25], [4, 29], [4, 30], [4, 31], [4, 32], [4, 33], [4, 34], [4, 35], [4, 36], [4, 37], [4, 38], [4, 39], [4, 40], [4, 41], [4, 42], [4, 46], [4, 47], [4, 48], [4, 49], [4, 52], [4, 53], [4, 54], [4, 55], [4, 56], [4, 57], [4, 58], [4, 59], [4, 60], [4, 61], [4, 62], [4, 63], [4, 64], [4, 65], [4, 66], [4, 67], [4, 68], [4, 69], [4, 70], [4, 71], [4, 72], [4, 73], [4, 74], [4, 75], [4, 98], [4, 99], [4, 100], [4, 101], [4, 102], [4, 103], [4, 104], [4, 105], [4, 106], [4, 112], [4, 114], [4, 149], [4, 150], [4, 151], [4, 152], [5, 15], [5, 16], [5, 17], [5, 18], [5, 23], [5, 24], [5, 25], [5, 29], [5, 30], [5, 31], [5, 32], [5, 33], [5, 34], [5, 35], [5, 36], [5, 37], [5, 38], [5, 39], [5, 40], [5, 41], [5, 42], [5, 43], [5, 44], [5, 45], [5, 46], [5, 47], [5, 48], [5, 49], [5, 50], [5, 51], [5, 52], [5, 53], [5, 54], [5, 55], [5, 56], [5, 57], [5, 58], [5, 59], [5, 60], [5, 61], [5, 62], [5, 63], [5, 64], [5, 65], [5, 66], [5, 67], [5, 68], [5, 69], [5, 70], [5, 99], [5, 100], [5, 101], [5, 102], [5, 103], [5, 104], [5, 105], [5, 106], [5, 107], [5, 108], [5, 109], [5, 110], [5, 114], [5, 115], [5, 119], [5, 120], [5, 121], [5, 129], [5, 130], [5, 131], [5, 132], [5, 145], [5, 146], [5, 147], [5, 148], [5, 149], [5, 150], [5, 151], [5, 152], [6, 15], [6, 16], [6, 17], [6, 18], [6, 19], [6, 20], [6, 21], [6, 22], [6, 23], [6, 24], [6, 25], [6, 26], [6, 27], [6, 28], [6, 29], [6, 30], [6, 31], [6, 32], [6, 33], [6, 34], [6, 35], [6, 36], [6, 37], [6, 38], [6, 39], [6, 40], [6, 41], [6, 42], [6, 43], [6, 44], [6, 45], [6, 46], [6, 47], [6, 48], [6, 49], [6, 50], [6, 51], [6, 52], [6, 53], [6, 54], [6, 55], [6, 56], [6, 57], [6, 58], [6, 59], [6, 60], [6, 61], [6, 62], [6, 63], [6, 64], [6, 65], [6, 66], [6, 67], [6, 102], [6, 103], [6, 104], [6, 105], [6, 106], [6, 107], [6, 108], [6, 109], [6, 110], [6, 111], [6, 112], [6, 113], [6, 114], [6, 115], [6, 116], [6, 117], [6, 118], [6, 119], [6, 120], [6, 121], [6, 140], [6, 141], [6, 142], [6, 148], [6, 149], [6, 150], [6, 151], [7, 11], [7, 15], [7, 16], [7, 17], [7, 18], [7, 22], [7, 23], [7, 24], [7, 25], [7, 26], [7, 27], [7, 28], [7, 29], [7, 30], [7, 31], [7, 32], [7, 33], [7, 34], [7, 35], [7, 36], [7, 40], [7, 41], [7, 42], [7, 43], [7, 44], [7, 45], [7, 46], [7, 47], [7, 48], [7, 49], [7, 50], [7, 51], [7, 52], [7, 53], [7, 54], [7, 55], [7, 56], [7, 57], [7, 58], [7, 59], [7, 60], [7, 61], [7, 62], [7, 63], [7, 105], [7, 106], [7, 107], [7, 108], [7, 109], [7, 110], [7, 111], [7, 112], [7, 113], [7, 114], [7, 115], [7, 116], [7, 117], [7, 118], [7, 119], [7, 120], [7, 121], [7, 122], [7, 130], [7, 136], [7, 137], [7, 145], [7, 146], [7, 147], [7, 148], [7, 149], [7, 150], [7, 151], [7, 152], [7, 153], [8, 3], [8, 4], [8, 12], [8, 13], [8, 14], [8, 15], [8, 16], [8, 24], [8, 25], [8, 26], [8, 30], [8, 31], [8, 32], [8, 33], [8, 34], [8, 35], [8, 36], [8, 37], [8, 38], [8, 39], [8, 40], [8, 41], [8, 42], [8, 43], [8, 44], [8, 45], [8, 46], [8, 47], [8, 48], [8, 49], [8, 50], [8, 53], [8, 54], [8, 55], [8, 56], [8, 57], [8, 58], [8, 59], [8, 60], [8, 61], [8, 106], [8, 107], [8, 108], [8, 109], [8, 110], [8, 111], [8, 112], [8, 113], [8, 114], [8, 115], [8, 116], [8, 117], [8, 118], [8, 119], [8, 120], [8, 121], [8, 122], [8, 127], [8, 132], [8, 133], [8, 134], [8, 135], [8, 136], [8, 137], [8, 138], [8, 139], [8, 140], [8, 141], [8, 142], [8, 143], [8, 144], [8, 145], [8, 146], [8, 147], [8, 148], [8, 149], [8, 150], [8, 151], [9, 20], [9, 21], [9, 22], [9, 30], [9, 31], [9, 32], [9, 33], [9, 34], [9, 35], [9, 36], [9, 37], [9, 38], [9, 39], [9, 40], [9, 41], [9, 42], [9, 43], [9, 44], [9, 45], [9, 46], [9, 47], [9, 48], [9, 49], [9, 50], [9, 51], [9, 52], [9, 53], [9, 54], [9, 55], [9, 56], [9, 57], [9, 109], [9, 110], [9, 111], [9, 112], [9, 113], [9, 114], [9, 115], [9, 116], [9, 117], [9, 118], [9, 119], [9, 120], [9, 121], [9, 122], [9, 123], [9, 124], [9, 125], [9, 127], [9, 130], [9, 132], [9, 133], [9, 134], [9, 135], [9, 136], [9, 140], [9, 141], [9, 142], [9, 143], [9, 144], [9, 145], [9, 146], [9, 147], [9, 148], [9, 149], [9, 150], [9, 151], [9, 154], [9, 155], [9, 163], [10, 19], [10, 20], [10, 21], [10, 22], [10, 27], [10, 28], [10, 29], [10, 30], [10, 31], [10, 32], [10, 33], [10, 34], [10, 35], [10, 36], [10, 37], [10, 38], [10, 39], [10, 42], [10, 43], [10, 44], [10, 45], [10, 46], [10, 47], [10, 48], [10, 49], [10, 50], [10, 51], [10, 52], [10, 53], [10, 54], [10, 55], [10, 56], [10, 57], [10, 58], [10, 108], [10, 109], [10, 110], [10, 111], [10, 112], [10, 113], [10, 114], [10, 115], [10, 116], [10, 117], [10, 118], [10, 119], [10, 120], [10, 121], [10, 122], [10, 123], [10, 124], [10, 125], [10, 126], [10, 127], [10, 128], [10, 129], [10, 130], [10, 131], [10, 132], [10, 133], [10, 134], [10, 135], [10, 136], [10, 137], [10, 142], [10, 143], [10, 144], [10, 145], [10, 146], [10, 147], [10, 148], [10, 149], [10, 150], [10, 151], [11, 15], [11, 16], [11, 19], [11, 20], [11, 21], [11, 26], [11, 27], [11, 30], [11, 31], [11, 32], [11, 33], [11, 34], [11, 35], [11, 36], [11, 37], [11, 38], [11, 39], [11, 40], [11, 41], [11, 42], [11, 43], [11, 44], [11, 45], [11, 46], [11, 47], [11, 48], [11, 49], [11, 53], [11, 54], [11, 55], [11, 56], [11, 57], [11, 109], [11, 110], [11, 111], [11, 112], [11, 113], [11, 114], [11, 115], [11, 116], [11, 117], [11, 118], [11, 119], [11, 120], [11, 121], [11, 122], [11, 132], [11, 133], [11, 134], [11, 135], [11, 136], [11, 137], [11, 138], [11, 139], [11, 140], [11, 141], [11, 142], [11, 143], [11, 144], [11, 145], [11, 146], [11, 147], [11, 148], [11, 149], [11, 150], [12, 0], [12, 1], [12, 2], [12, 3], [12, 12], [12, 13], [12, 14], [12, 15], [12, 16], [12, 19], [12, 20], [12, 21], [12, 22], [12, 26], [12, 27], [12, 28], [12, 29], [12, 30], [12, 31], [12, 32], [12, 33], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [12, 40], [12, 41], [12, 42], [12, 43], [12, 44], [12, 45], [12, 46], [12, 47], [12, 111], [12, 112], [12, 113], [12, 114], [12, 115], [12, 116], [12, 117], [12, 118], [12, 119], [12, 120], [12, 121], [12, 122], [12, 123], [12, 124], [12, 125], [12, 126], [12, 127], [12, 128], [12, 129], [12, 132], [12, 133], [12, 134], [12, 135], [12, 136], [12, 137], [12, 138], [12, 139], [12, 140], [12, 141], [12, 142], [12, 143], [12, 144], [12, 145], [12, 146], [12, 147], [12, 148], [13, 1], [13, 2], [13, 11], [13, 12], [13, 15], [13, 16], [13, 17], [13, 24], [13, 25], [13, 26], [13, 27], [13, 28], [13, 30], [13, 31], [13, 32], [13, 33], [13, 34], [13, 35], [13, 36], [13, 37], [13, 38], [13, 39], [13, 40], [13, 41], [13, 42], [13, 43], [13, 44], [13, 45], [13, 98], [13, 116], [13, 117], [13, 118], [13, 119], [13, 120], [13, 121], [13, 122], [13, 123], [13, 124], [13, 125], [13, 126], [13, 127], [13, 128], [13, 129], [13, 130], [13, 131], [13, 132], [13, 133], [13, 134], [13, 135], [13, 137], [13, 139], [13, 140], [13, 141], [13, 142], [13, 143], [13, 144], [13, 145], [13, 146], [13, 147], [13, 148], [13, 149], [14, 3], [14, 18], [14, 19], [14, 20], [14, 21], [14, 25], [14, 26], [14, 27], [14, 28], [14, 29], [14, 30], [14, 31], [14, 32], [14, 33], [14, 34], [14, 35], [14, 36], [14, 37], [14, 38], [14, 39], [14, 40], [14, 41], [14, 42], [14, 43], [14, 44], [14, 59], [14, 60], [14, 84], [14, 97], [14, 98], [14, 102], [14, 116], [14, 117], [14, 118], [14, 119], [14, 120], [14, 121], [14, 122], [14, 123], [14, 124], [14, 125], [14, 126], [14, 127], [14, 128], [14, 129], [14, 130], [14, 131], [14, 132], [14, 133], [14, 134], [14, 135], [14, 136], [14, 137], [14, 138], [14, 139], [14, 140], [14, 141], [14, 142], [14, 143], [14, 144], [14, 145], [14, 146], [14, 147], [14, 153], [14, 154], [15, 12], [15, 13], [15, 18], [15, 19], [15, 20], [15, 21], [15, 22], [15, 23], [15, 24], [15, 25], [15, 26], [15, 27], [15, 28], [15, 29], [15, 30], [15, 31], [15, 32], [15, 33], [15, 34], [15, 35], [15, 36], [15, 37], [15, 38], [15, 39], [15, 40], [15, 41], [15, 57], [15, 58], [15, 59], [15, 60], [15, 68], [15, 69], [15, 119], [15, 120], [15, 121], [15, 122], [15, 123], [15, 124], [15, 125], [15, 126], [15, 127], [15, 128], [15, 129], [15, 130], [15, 131], [15, 132], [15, 133], [15, 134], [15, 135], [15, 136], [15, 137], [15, 138], [15, 139], [15, 140], [15, 141], [15, 142], [15, 143], [15, 144], [15, 145], [15, 151], [15, 152], [15, 153], [16, 1], [16, 2], [16, 3], [16, 4], [16, 18], [16, 19], [16, 20], [16, 23], [16, 24], [16, 25], [16, 26], [16, 28], [16, 29], [16, 30], [16, 31], [16, 32], [16, 33], [16, 34], [16, 35], [16, 36], [16, 37], [16, 38], [16, 39], [16, 40], [16, 62], [16, 63], [16, 64], [16, 65], [16, 73], [16, 74], [16, 79], [16, 80], [16, 109], [16, 110], [16, 111], [16, 112], [16, 123], [16, 124], [16, 125], [16, 126], [16, 127], [16, 128], [16, 129], [16, 130], [16, 131], [16, 132], [16, 133], [16, 134], [16, 135], [16, 136], [16, 137], [16, 138], [16, 139], [16, 140], [16, 141], [16, 142], [16, 143], [16, 144], [17, 7], [17, 8], [17, 17], [17, 18], [17, 22], [17, 23], [17, 24], [17, 25], [17, 26], [17, 27], [17, 28], [17, 29], [17, 30], [17, 31], [17, 32], [17, 33], [17, 34], [17, 35], [17, 36], [17, 37], [17, 38], [17, 39], [17, 40], [17, 49], [17, 50], [17, 55], [17, 61], [17, 62], [17, 63], [17, 64], [17, 65], [17, 69], [17, 70], [17, 71], [17, 72], [17, 79], [17, 80], [17, 81], [17, 82], [17, 107], [17, 108], [17, 110], [17, 111], [17, 115], [17, 116], [17, 124], [17, 125], [17, 126], [17, 127], [17, 128], [17, 129], [17, 130], [17, 131], [17, 132], [17, 133], [17, 134], [17, 135], [17, 136], [17, 137], [17, 138], [17, 139], [17, 140], [17, 141], [17, 142], [18, 0], [18, 1], [18, 2], [18, 14], [18, 15], [18, 16], [18, 17], [18, 18], [18, 19], [18, 20], [18, 21], [18, 22], [18, 23], [18, 24], [18, 25], [18, 26], [18, 27], [18, 28], [18, 29], [18, 30], [18, 31], [18, 32], [18, 33], [18, 34], [18, 35], [18, 36], [18, 37], [18, 38], [18, 39], [18, 49], [18, 50], [18, 53], [18, 54], [18, 58], [18, 59], [18, 63], [18, 64], [18, 65], [18, 66], [18, 68], [18, 69], [18, 70], [18, 71], [18, 102], [18, 103], [18, 104], [18, 105], [18, 106], [18, 107], [18, 108], [18, 109], [18, 110], [18, 115], [18, 116], [18, 125], [18, 126], [18, 127], [18, 128], [18, 129], [18, 130], [18, 131], [18, 132], [18, 133], [18, 134], [18, 135], [18, 136], [18, 137], [18, 138], [19, 1], [19, 2], [19, 3], [19, 14], [19, 15], [19, 16], [19, 17], [19, 18], [19, 19], [19, 20], [19, 21], [19, 22], [19, 24], [19, 25], [19, 26], [19, 27], [19, 28], [19, 29], [19, 30], [19, 31], [19, 32], [19, 33], [19, 34], [19, 35], [19, 36], [19, 37], [19, 38], [19, 48], [19, 49], [19, 50], [19, 51], [19, 52], [19, 53], [19, 54], [19, 55], [19, 56], [19, 57], [19, 61], [19, 62], [19, 63], [19, 64], [19, 65], [19, 66], [19, 67], [19, 68], [19, 69], [19, 70], [19, 80], [19, 81], [19, 82], [19, 108], [19, 111], [19, 112], [19, 113], [19, 114], [19, 115], [19, 116], [19, 117], [19, 118], [19, 119], [19, 127], [19, 128], [19, 129], [19, 130], [19, 131], [19, 132], [19, 133], [19, 134], [19, 135], [19, 136], [19, 137], [20, 0], [20, 1], [20, 2], [20, 5], [20, 6], [20, 7], [20, 8], [20, 13], [20, 14], [20, 15], [20, 17], [20, 18], [20, 19], [20, 20], [20, 21], [20, 22], [20, 23], [20, 24], [20, 25], [20, 26], [20, 27], [20, 28], [20, 29], [20, 30], [20, 31], [20, 32], [20, 33], [20, 34], [20, 47], [20, 48], [20, 49], [20, 50], [20, 51], [20, 52], [20, 53], [20, 56], [20, 57], [20, 58], [20, 62], [20, 63], [20, 64], [20, 65], [20, 66], [20, 67], [20, 68], [20, 69], [20, 74], [20, 75], [20, 80], [20, 81], [20, 99], [20, 100], [20, 101], [20, 102], [20, 107], [20, 108], [20, 109], [20, 110], [20, 111], [20, 112], [20, 113], [20, 114], [20, 115], [20, 116], [20, 117], [20, 118], [20, 119], [20, 122], [20, 123], [20, 128], [20, 129], [20, 130], [20, 131], [20, 132], [20, 133], [20, 134], [21, 2], [21, 3], [21, 4], [21, 5], [21, 6], [21, 7], [21, 12], [21, 13], [21, 14], [21, 15], [21, 17], [21, 18], [21, 19], [21, 20], [21, 21], [21, 22], [21, 26], [21, 27], [21, 28], [21, 29], [21, 30], [21, 31], [21, 32], [21, 45], [21, 46], [21, 47], [21, 48], [21, 49], [21, 50], [21, 51], [21, 52], [21, 53], [21, 54], [21, 55], [21, 56], [21, 57], [21, 58], [21, 59], [21, 60], [21, 61], [21, 62], [21, 63], [21, 64], [21, 65], [21, 66], [21, 67], [21, 68], [21, 69], [21, 70], [21, 71], [21, 72], [21, 75], [21, 76], [21, 80], [21, 81], [21, 82], [21, 96], [21, 97], [21, 98], [21, 99], [21, 100], [21, 101], [21, 102], [21, 103], [21, 110], [21, 111], [21, 112], [21, 113], [21, 114], [21, 115], [21, 116], [21, 117], [21, 118], [21, 149], [21, 150], [22, 1], [22, 2], [22, 3], [22, 4], [22, 5], [22, 6], [22, 7], [22, 10], [22, 11], [22, 12], [22, 13], [22, 14], [22, 15], [22, 19], [22, 20], [22, 21], [22, 22], [22, 23], [22, 25], [22, 26], [22, 27], [22, 28], [22, 29], [22, 30], [22, 31], [22, 44], [22, 45], [22, 46], [22, 47], [22, 48], [22, 49], [22, 50], [22, 51], [22, 52], [22, 53], [22, 54], [22, 55], [22, 57], [22, 59], [22, 60], [22, 61], [22, 62], [22, 63], [22, 64], [22, 65], [22, 66], [22, 67], [22, 68], [22, 69], [22, 70], [22, 71], [22, 72], [22, 73], [22, 74], [22, 96], [22, 97], [22, 98], [22, 99], [22, 100], [22, 101], [22, 111], [22, 112], [22, 113], [22, 114], [22, 115], [22, 116], [22, 117], [22, 128], [22, 129], [22, 130], [22, 150], [22, 151], [22, 152], [23, 0], [23, 1], [23, 2], [23, 3], [23, 4], [23, 5], [23, 6], [23, 7], [23, 11], [23, 12], [23, 13], [23, 14], [23, 15], [23, 16], [23, 19], [23, 20], [23, 21], [23, 22], [23, 23], [23, 24], [23, 25], [23, 26], [23, 27], [23, 29], [23, 42], [23, 43], [23, 44], [23, 45], [23, 46], [23, 47], [23, 48], [23, 49], [23, 50], [23, 51], [23, 52], [23, 53], [23, 56], [23, 57], [23, 58], [23, 61], [23, 62], [23, 63], [23, 64], [23, 65], [23, 66], [23, 67], [23, 68], [23, 72], [23, 73], [23, 74], [23, 75], [23, 76], [23, 88], [23, 89], [23, 90], [23, 112], [23, 113], [23, 114], [23, 115], [23, 116], [23, 128], [24, 0], [24, 1], [24, 2], [24, 3], [24, 4], [24, 5], [24, 6], [24, 11], [24, 12], [24, 13], [24, 14], [24, 19], [24, 20], [24, 21], [24, 22], [24, 23], [24, 24], [24, 25], [24, 26], [24, 27], [24, 28], [24, 29], [24, 39], [24, 41], [24, 42], [24, 43], [24, 49], [24, 50], [24, 51], [24, 55], [24, 56], [24, 57], [24, 58], [24, 59], [24, 60], [24, 61], [24, 62], [24, 63], [24, 64], [24, 65], [24, 66], [24, 67], [24, 72], [24, 73], [24, 74], [24, 87], [24, 88], [24, 89], [24, 91], [24, 92], [24, 93], [24, 100], [24, 101], [24, 105], [24, 106], [24, 107], [24, 108], [24, 121], [25, 13], [25, 14], [25, 15], [25, 16], [25, 17], [25, 18], [25, 19], [25, 20], [25, 21], [25, 22], [25, 23], [25, 24], [25, 25], [25, 26], [25, 27], [25, 28], [25, 33], [25, 34], [25, 35], [25, 36], [25, 37], [25, 38], [25, 39], [25, 40], [25, 41], [25, 42], [25, 43], [25, 44], [25, 51], [25, 52], [25, 53], [25, 54], [25, 55], [25, 56], [25, 57], [25, 58], [25, 59], [25, 60], [25, 61], [25, 62], [25, 63], [25, 64], [25, 65], [25, 66], [25, 67], [25, 68], [25, 69], [25, 70], [25, 71], [25, 72], [25, 73], [25, 74], [25, 75], [25, 76], [25, 77], [25, 78], [25, 81], [25, 82], [25, 86], [25, 87], [25, 88], [25, 100], [25, 110], [25, 111], [25, 112], [25, 113], [25, 118], [25, 127], [25, 128], [25, 129], [26, 1], [26, 13], [26, 14], [26, 15], [26, 16], [26, 19], [26, 20], [26, 21], [26, 22], [26, 23], [26, 24], [26, 25], [26, 26], [26, 27], [26, 28], [26, 29], [26, 31], [26, 32], [26, 33], [26, 34], [26, 35], [26, 36], [26, 37], [26, 38], [26, 39], [26, 40], [26, 41], [26, 52], [26, 53], [26, 54], [26, 55], [26, 56], [26, 57], [26, 58], [26, 59], [26, 60], [26, 61], [26, 62], [26, 63], [26, 64], [26, 65], [26, 66], [26, 67], [26, 68], [26, 69], [26, 70], [26, 71], [26, 72], [26, 73], [26, 74], [26, 75], [26, 76], [26, 77], [26, 78], [26, 79], [26, 80], [26, 81], [26, 82], [26, 83], [26, 84], [26, 85], [26, 87], [26, 88], [26, 89], [26, 101], [26, 107], [26, 112], [26, 113], [26, 126], [26, 127], [26, 128], [26, 129], [26, 130], [26, 131], [26, 146], [26, 147], [26, 149], [26, 150], [26, 151], [26, 152], [27, 0], [27, 1], [27, 2], [27, 3], [27, 4], [27, 11], [27, 12], [27, 13], [27, 14], [27, 15], [27, 16], [27, 17], [27, 18], [27, 19], [27, 20], [27, 21], [27, 22], [27, 23], [27, 24], [27, 25], [27, 26], [27, 27], [27, 28], [27, 29], [27, 30], [27, 31], [27, 32], [27, 33], [27, 34], [27, 35], [27, 36], [27, 37], [27, 38], [27, 39], [27, 40], [27, 49], [27, 50], [27, 51], [27, 52], [27, 53], [27, 54], [27, 55], [27, 56], [27, 57], [27, 58], [27, 59], [27, 60], [27, 61], [27, 62], [27, 63], [27, 64], [27, 65], [27, 66], [27, 67], [27, 68], [27, 69], [27, 70], [27, 71], [27, 72], [27, 73], [27, 74], [27, 75], [27, 76], [27, 77], [27, 78], [27, 79], [27, 80], [27, 81], [27, 82], [27, 83], [27, 84], [27, 85], [27, 86], [27, 87], [27, 88], [27, 89], [27, 105], [27, 106], [27, 107], [27, 108], [27, 110], [27, 129], [27, 130], [27, 131], [27, 132], [27, 145], [27, 146], [28, 0], [28, 1], [28, 2], [28, 3], [28, 4], [28, 5], [28, 6], [28, 7], [28, 8], [28, 9], [28, 10], [28, 14], [28, 15], [28, 16], [28, 17], [28, 18], [28, 19], [28, 20], [28, 21], [28, 22], [28, 23], [28, 24], [28, 25], [28, 26], [28, 27], [28, 28], [28, 29], [28, 30], [28, 37], [28, 39], [28, 48], [28, 49], [28, 50], [28, 51], [28, 52], [28, 53], [28, 54], [28, 55], [28, 56], [28, 57], [28, 63], [28, 64], [28, 65], [28, 66], [28, 67], [28, 68], [28, 69], [28, 70], [28, 71], [28, 72], [28, 73], [28, 74], [28, 75], [28, 76], [28, 77], [28, 78], [28, 79], [28, 80], [28, 81], [28, 82], [28, 83], [28, 84], [28, 85], [28, 86], [28, 87], [28, 88], [28, 89], [28, 90], [28, 99], [28, 100], [28, 101], [28, 102], [28, 103], [28, 104], [28, 105], [28, 106], [28, 130], [28, 131], [28, 132], [28, 133], [29, 0], [29, 1], [29, 2], [29, 3], [29, 4], [29, 5], [29, 6], [29, 7], [29, 8], [29, 9], [29, 10], [29, 11], [29, 12], [29, 13], [29, 14], [29, 15], [29, 16], [29, 17], [29, 18], [29, 19], [29, 20], [29, 21], [29, 22], [29, 23], [29, 24], [29, 25], [29, 26], [29, 29], [29, 30], [29, 31], [29, 33], [29, 34], [29, 35], [29, 36], [29, 37], [29, 38], [29, 39], [29, 48], [29, 49], [29, 50], [29, 51], [29, 52], [29, 53], [29, 54], [29, 55], [29, 56], [29, 57], [29, 58], [29, 59], [29, 60], [29, 61], [29, 62], [29, 63], [29, 64], [29, 67], [29, 68], [29, 69], [29, 70], [29, 71], [29, 74], [29, 75], [29, 76], [29, 77], [29, 78], [29, 79], [29, 80], [29, 81], [29, 82], [29, 83], [29, 84], [29, 85], [29, 86], [29, 87], [29, 88], [29, 97], [29, 98], [29, 99], [29, 100], [29, 105], [29, 106], [29, 107], [29, 108], [29, 127], [29, 128], [29, 129], [29, 130], [29, 131], [29, 132], [29, 133], [29, 134], [29, 143], [29, 144], [30, 0], [30, 1], [30, 2], [30, 3], [30, 4], [30, 5], [30, 6], [30, 7], [30, 8], [30, 13], [30, 14], [30, 15], [30, 16], [30, 17], [30, 18], [30, 19], [30, 20], [30, 21], [30, 22], [30, 23], [30, 24], [30, 25], [30, 26], [30, 27], [30, 28], [30, 29], [30, 30], [30, 31], [30, 32], [30, 33], [30, 34], [30, 35], [30, 36], [30, 37], [30, 38], [30, 39], [30, 40], [30, 41], [30, 42], [30, 43], [30, 44], [30, 45], [30, 46], [30, 47], [30, 48], [30, 49], [30, 50], [30, 51], [30, 52], [30, 53], [30, 54], [30, 55], [30, 56], [30, 57], [30, 58], [30, 59], [30, 60], [30, 61], [30, 64], [30, 65], [30, 66], [30, 67], [30, 68], [30, 69], [30, 70], [30, 71], [30, 74], [30, 75], [30, 76], [30, 77], [30, 78], [30, 79], [30, 80], [30, 81], [30, 82], [30, 83], [30, 84], [30, 85], [30, 91], [30, 92], [30, 97], [30, 98], [30, 99], [30, 105], [30, 106], [30, 117], [30, 122], [30, 126], [30, 127], [30, 128], [30, 129], [30, 130], [30, 131], [30, 132], [30, 143], [30, 144], [30, 145], [30, 146], [30, 150], [31, 0], [31, 1], [31, 2], [31, 3], [31, 4], [31, 5], [31, 6], [31, 7], [31, 8], [31, 9], [31, 14], [31, 15], [31, 16], [31, 17], [31, 18], [31, 19], [31, 20], [31, 21], [31, 22], [31, 23], [31, 24], [31, 25], [31, 26], [31, 27], [31, 28], [31, 29], [31, 30], [31, 33], [31, 34], [31, 35], [31, 36], [31, 37], [31, 40], [31, 41], [31, 42], [31, 43], [31, 44], [31, 45], [31, 46], [31, 47], [31, 48], [31, 49], [31, 50], [31, 51], [31, 52], [31, 53], [31, 54], [31, 55], [31, 56], [31, 57], [31, 58], [31, 59], [31, 60], [31, 61], [31, 62], [31, 63], [31, 64], [31, 65], [31, 66], [31, 67], [31, 68], [31, 69], [31, 70], [31, 71], [31, 72], [31, 73], [31, 74], [31, 75], [31, 78], [31, 79], [31, 80], [31, 81], [31, 82], [31, 84], [31, 94], [31, 95], [31, 96], [31, 97], [31, 98], [31, 116], [31, 117], [31, 129], [31, 130], [31, 131], [31, 132], [31, 133], [31, 134], [31, 143], [31, 144], [31, 145], [31, 146], [32, 1], [32, 2], [32, 3], [32, 4], [32, 5], [32, 6], [32, 7], [32, 8], [32, 9], [32, 14], [32, 15], [32, 16], [32, 17], [32, 18], [32, 19], [32, 20], [32, 21], [32, 22], [32, 23], [32, 24], [32, 25], [32, 28], [32, 29], [32, 30], [32, 31], [32, 32], [32, 33], [32, 34], [32, 35], [32, 36], [32, 37], [32, 38], [32, 42], [32, 43], [32, 44], [32, 45], [32, 46], [32, 47], [32, 48], [32, 49], [32, 50], [32, 51], [32, 52], [32, 53], [32, 54], [32, 56], [32, 57], [32, 58], [32, 59], [32, 60], [32, 61], [32, 65], [32, 66], [32, 67], [32, 68], [32, 69], [32, 74], [32, 75], [32, 76], [32, 77], [32, 78], [32, 79], [32, 80], [32, 81], [32, 82], [32, 83], [32, 84], [32, 85], [32, 89], [32, 90], [32, 91], [32, 92], [32, 96], [32, 97], [32, 98], [32, 99], [32, 100], [32, 124], [32, 125], [32, 126], [32, 130], [32, 131], [32, 132], [32, 143], [32, 144], [33, 0], [33, 1], [33, 2], [33, 3], [33, 4], [33, 5], [33, 6], [33, 8], [33, 9], [33, 10], [33, 11], [33, 12], [33, 13], [33, 14], [33, 15], [33, 16], [33, 17], [33, 18], [33, 19], [33, 20], [33, 21], [33, 22], [33, 23], [33, 24], [33, 25], [33, 26], [33, 27], [33, 28], [33, 29], [33, 30], [33, 31], [33, 32], [33, 33], [33, 34], [33, 35], [33, 36], [33, 37], [33, 38], [33, 39], [33, 46], [33, 47], [33, 48], [33, 49], [33, 50], [33, 51], [33, 52], [33, 53], [33, 60], [33, 61], [33, 62], [33, 63], [33, 64], [33, 65], [33, 66], [33, 67], [33, 68], [33, 69], [33, 70], [33, 73], [33, 74], [33, 75], [33, 76], [33, 77], [33, 78], [33, 79], [33, 80], [33, 81], [33, 82], [33, 83], [33, 84], [33, 85], [33, 86], [33, 87], [33, 88], [33, 89], [33, 102], [33, 103], [33, 104], [33, 105], [33, 109], [33, 110], [33, 123], [33, 124], [33, 131], [33, 132], [33, 142], [33, 143], [33, 144], [33, 145], [33, 146], [33, 163], [34, 0], [34, 1], [34, 2], [34, 3], [34, 4], [34, 5], [34, 6], [34, 7], [34, 8], [34, 9], [34, 10], [34, 11], [34, 12], [34, 13], [34, 14], [34, 15], [34, 16], [34, 17], [34, 18], [34, 19], [34, 20], [34, 21], [34, 22], [34, 23], [34, 24], [34, 25], [34, 26], [34, 27], [34, 28], [34, 29], [34, 30], [34, 31], [34, 34], [34, 35], [34, 36], [34, 37], [34, 38], [34, 45], [34, 46], [34, 47], [34, 48], [34, 49], [34, 50], [34, 51], [34, 52], [34, 53], [34, 63], [34, 64], [34, 65], [34, 66], [34, 67], [34, 68], [34, 69], [34, 70], [34, 71], [34, 72], [34, 73], [34, 74], [34, 75], [34, 76], [34, 77], [34, 86], [34, 90], [34, 91], [34, 92], [34, 93], [34, 94], [34, 95], [34, 96], [34, 97], [34, 101], [34, 102], [34, 116], [34, 117], [34, 118], [34, 122], [34, 123], [34, 124], [34, 125], [34, 130], [34, 131], [34, 132], [34, 133], [34, 134], [34, 135], [34, 142], [34, 143], [34, 144], [34, 145], [34, 146], [35, 0], [35, 1], [35, 2], [35, 3], [35, 4], [35, 5], [35, 6], [35, 7], [35, 8], [35, 9], [35, 10], [35, 11], [35, 12], [35, 13], [35, 14], [35, 15], [35, 16], [35, 17], [35, 18], [35, 19], [35, 20], [35, 21], [35, 22], [35, 23], [35, 24], [35, 25], [35, 26], [35, 27], [35, 28], [35, 29], [35, 30], [35, 31], [35, 32], [35, 33], [35, 34], [35, 35], [35, 36], [35, 37], [35, 38], [35, 39], [35, 53], [35, 54], [35, 55], [35, 56], [35, 57], [35, 58], [35, 60], [35, 61], [35, 62], [35, 63], [35, 64], [35, 65], [35, 66], [35, 67], [35, 68], [35, 69], [35, 70], [35, 71], [35, 72], [35, 73], [35, 74], [35, 75], [35, 76], [35, 77], [35, 78], [35, 82], [35, 83], [35, 84], [35, 85], [35, 92], [35, 93], [35, 94], [35, 95], [35, 96], [35, 97], [35, 98], [35, 99], [35, 100], [35, 101], [35, 121], [35, 122], [35, 123], [35, 129], [35, 130], [35, 131], [35, 132], [35, 133], [35, 134], [35, 135], [36, 0], [36, 1], [36, 2], [36, 3], [36, 4], [36, 5], [36, 6], [36, 7], [36, 8], [36, 9], [36, 10], [36, 11], [36, 12], [36, 13], [36, 14], [36, 15], [36, 16], [36, 17], [36, 18], [36, 19], [36, 20], [36, 21], [36, 22], [36, 23], [36, 24], [36, 30], [36, 31], [36, 32], [36, 33], [36, 34], [36, 35], [36, 36], [36, 37], [36, 38], [36, 39], [36, 40], [36, 41], [36, 42], [36, 43], [36, 44], [36, 45], [36, 53], [36, 54], [36, 55], [36, 56], [36, 57], [36, 58], [36, 59], [36, 60], [36, 61], [36, 62], [36, 63], [36, 64], [36, 67], [36, 68], [36, 69], [36, 70], [36, 71], [36, 72], [36, 73], [36, 74], [36, 75], [36, 76], [36, 77], [36, 78], [36, 89], [36, 90], [36, 91], [36, 93], [36, 94], [36, 95], [36, 96], [36, 97], [36, 98], [36, 99], [36, 100], [36, 101], [36, 102], [36, 110], [36, 111], [36, 112], [36, 113], [36, 114], [36, 115], [36, 121], [36, 127], [36, 128], [36, 129], [36, 130], [36, 131], [36, 132], [37, 1], [37, 2], [37, 3], [37, 4], [37, 5], [37, 6], [37, 7], [37, 8], [37, 9], [37, 10], [37, 11], [37, 12], [37, 13], [37, 14], [37, 15], [37, 16], [37, 17], [37, 18], [37, 19], [37, 20], [37, 21], [37, 22], [37, 23], [37, 24], [37, 25], [37, 26], [37, 34], [37, 35], [37, 36], [37, 37], [37, 38], [37, 39], [37, 41], [37, 42], [37, 43], [37, 44], [37, 45], [37, 46], [37, 47], [37, 63], [37, 64], [37, 65], [37, 66], [37, 67], [37, 68], [37, 69], [37, 70], [37, 71], [37, 72], [37, 73], [37, 74], [37, 75], [37, 76], [37, 77], [37, 78], [37, 89], [37, 90], [37, 91], [37, 92], [37, 93], [37, 98], [37, 101], [37, 102], [37, 103], [37, 104], [37, 109], [37, 110], [37, 111], [37, 112], [37, 113], [37, 114], [37, 115], [37, 116], [37, 118], [37, 119], [37, 120], [37, 121], [37, 125], [37, 126], [37, 127], [37, 128], [37, 129], [37, 130], [37, 131], [37, 132], [37, 133], [37, 134], [37, 135], [37, 142], [37, 143], [37, 144], [37, 145], [37, 146], [37, 150], [37, 151], [38, 4], [38, 5], [38, 6], [38, 7], [38, 8], [38, 9], [38, 10], [38, 11], [38, 12], [38, 13], [38, 14], [38, 15], [38, 16], [38, 17], [38, 18], [38, 19], [38, 20], [38, 21], [38, 22], [38, 23], [38, 24], [38, 25], [38, 26], [38, 36], [38, 37], [38, 44], [38, 45], [38, 46], [38, 47], [38, 48], [38, 51], [38, 52], [38, 53], [38, 54], [38, 55], [38, 56], [38, 57], [38, 58], [38, 59], [38, 60], [38, 61], [38, 62], [38, 63], [38, 64], [38, 65], [38, 66], [38, 67], [38, 68], [38, 69], [38, 70], [38, 71], [38, 72], [38, 73], [38, 76], [38, 77], [38, 78], [38, 79], [38, 80], [38, 81], [38, 83], [38, 84], [38, 85], [38, 88], [38, 89], [38, 90], [38, 91], [38, 92], [38, 99], [38, 100], [38, 101], [38, 102], [38, 103], [38, 104], [38, 105], [38, 121], [38, 127], [38, 128], [38, 129], [38, 130], [38, 131], [38, 132], [38, 133], [38, 142], [38, 143], [38, 144], [38, 145], [38, 146], [38, 147], [38, 148], [38, 149], [39, 0], [39, 1], [39, 2], [39, 3], [39, 4], [39, 5], [39, 6], [39, 7], [39, 8], [39, 9], [39, 10], [39, 11], [39, 12], [39, 13], [39, 14], [39, 15], [39, 16], [39, 17], [39, 18], [39, 19], [39, 22], [39, 23], [39, 24], [39, 25], [39, 26], [39, 50], [39, 51], [39, 52], [39, 53], [39, 54], [39, 55], [39, 56], [39, 60], [39, 61], [39, 62], [39, 63], [39, 64], [39, 65], [39, 66], [39, 67], [39, 68], [39, 69], [39, 70], [39, 71], [39, 72], [39, 73], [39, 74], [39, 75], [39, 76], [39, 77], [39, 78], [39, 79], [39, 80], [39, 81], [39, 82], [39, 83], [39, 84], [39, 85], [39, 87], [39, 93], [39, 94], [39, 95], [39, 96], [39, 97], [39, 100], [39, 101], [39, 102], [39, 103], [39, 104], [39, 114], [39, 115], [39, 122], [39, 123], [39, 124], [39, 125], [39, 126], [39, 127], [39, 129], [39, 130], [39, 131], [39, 132], [39, 133], [39, 134], [39, 135], [39, 136], [39, 137], [39, 143], [39, 144], [39, 145], [39, 146], [39, 147], [39, 148], [39, 149], [40, 4], [40, 5], [40, 6], [40, 7], [40, 8], [40, 9], [40, 10], [40, 11], [40, 12], [40, 13], [40, 14], [40, 15], [40, 16], [40, 17], [40, 18], [40, 19], [40, 20], [40, 21], [40, 22], [40, 25], [40, 26], [40, 27], [40, 28], [40, 46], [40, 47], [40, 48], [40, 49], [40, 50], [40, 60], [40, 61], [40, 62], [40, 63], [40, 64], [40, 65], [40, 66], [40, 67], [40, 68], [40, 69], [40, 70], [40, 71], [40, 72], [40, 73], [40, 74], [40, 75], [40, 78], [40, 79], [40, 80], [40, 81], [40, 82], [40, 83], [40, 84], [40, 85], [40, 86], [40, 90], [40, 91], [40, 92], [40, 93], [40, 94], [40, 95], [40, 98], [40, 99], [40, 100], [40, 101], [40, 102], [40, 103], [40, 104], [40, 105], [40, 106], [40, 113], [40, 114], [40, 115], [40, 116], [40, 122], [40, 123], [40, 124], [40, 125], [40, 126], [40, 127], [40, 128], [40, 129], [40, 132], [40, 133], [40, 134], [40, 135], [40, 136], [40, 137], [40, 143], [40, 144], [40, 145], [40, 146], [40, 147], [41, 14], [41, 15], [41, 16], [41, 17], [41, 18], [41, 19], [41, 20], [41, 21], [41, 24], [41, 25], [41, 26], [41, 27], [41, 28], [41, 45], [41, 46], [41, 47], [41, 48], [41, 49], [41, 53], [41, 54], [41, 57], [41, 58], [41, 59], [41, 60], [41, 61], [41, 62], [41, 63], [41, 64], [41, 65], [41, 66], [41, 67], [41, 68], [41, 69], [41, 70], [41, 71], [41, 72], [41, 73], [41, 74], [41, 75], [41, 76], [41, 77], [41, 78], [41, 79], [41, 80], [41, 81], [41, 82], [41, 83], [41, 84], [41, 89], [41, 90], [41, 91], [41, 92], [41, 93], [41, 96], [41, 97], [41, 98], [41, 99], [41, 100], [41, 101], [41, 102], [41, 105], [41, 106], [41, 107], [41, 113], [41, 114], [41, 115], [41, 119], [41, 120], [41, 121], [41, 122], [41, 123], [41, 124], [41, 133], [41, 134], [41, 135], [41, 136], [41, 142], [41, 143], [41, 144], [41, 145], [41, 153], [41, 154], [41, 155], [41, 156], [42, 15], [42, 16], [42, 17], [42, 18], [42, 19], [42, 20], [42, 21], [42, 22], [42, 23], [42, 24], [42, 25], [42, 26], [42, 49], [42, 50], [42, 51], [42, 52], [42, 54], [42, 55], [42, 56], [42, 57], [42, 58], [42, 59], [42, 60], [42, 61], [42, 62], [42, 63], [42, 64], [42, 65], [42, 66], [42, 67], [42, 68], [42, 69], [42, 75], [42, 76], [42, 77], [42, 78], [42, 79], [42, 80], [42, 81], [42, 82], [42, 83], [42, 89], [42, 90], [42, 91], [42, 92], [42, 93], [42, 95], [42, 96], [42, 97], [42, 98], [42, 99], [42, 100], [42, 101], [42, 102], [42, 103], [42, 104], [42, 113], [42, 114], [42, 115], [42, 116], [42, 117], [42, 118], [42, 119], [42, 130], [42, 131], [42, 132], [42, 133], [42, 134], [42, 135], [42, 136], [42, 145], [42, 146], [42, 151], [42, 152], [42, 153], [43, 16], [43, 17], [43, 18], [43, 19], [43, 23], [43, 27], [43, 45], [43, 46], [43, 54], [43, 55], [43, 56], [43, 57], [43, 58], [43, 59], [43, 60], [43, 61], [43, 62], [43, 63], [43, 64], [43, 65], [43, 66], [43, 67], [43, 68], [43, 69], [43, 76], [43, 77], [43, 78], [43, 79], [43, 80], [43, 81], [43, 82], [43, 83], [43, 85], [43, 86], [43, 87], [43, 88], [43, 89], [43, 90], [43, 91], [43, 92], [43, 93], [43, 94], [43, 95], [43, 96], [43, 97], [43, 98], [43, 99], [43, 100], [43, 101], [43, 102], [43, 103], [43, 104], [43, 105], [43, 106], [43, 110], [43, 111], [43, 115], [43, 116], [43, 117], [43, 130], [43, 131], [43, 132], [43, 133], [43, 134], [43, 135], [43, 136], [43, 143], [43, 144], [43, 145], [43, 146], [43, 147], [43, 150], [43, 151], [44, 15], [44, 16], [44, 17], [44, 18], [44, 19], [44, 20], [44, 23], [44, 24], [44, 25], [44, 26], [44, 27], [44, 28], [44, 29], [44, 44], [44, 45], [44, 46], [44, 49], [44, 50], [44, 59], [44, 60], [44, 61], [44, 62], [44, 63], [44, 64], [44, 65], [44, 66], [44, 67], [44, 68], [44, 69], [44, 74], [44, 75], [44, 76], [44, 77], [44, 78], [44, 79], [44, 80], [44, 81], [44, 84], [44, 85], [44, 86], [44, 87], [44, 90], [44, 91], [44, 92], [44, 93], [44, 94], [44, 95], [44, 96], [44, 97], [44, 98], [44, 101], [44, 102], [44, 103], [44, 109], [44, 110], [44, 111], [44, 115], [44, 116], [44, 117], [44, 127], [44, 128], [44, 129], [44, 130], [44, 131], [44, 132], [44, 133], [44, 134], [44, 135], [44, 136], [44, 144], [44, 145], [44, 146], [44, 147], [44, 148], [44, 149], [44, 150], [44, 151], [44, 152], [45, 16], [45, 17], [45, 18], [45, 19], [45, 20], [45, 21], [45, 26], [45, 27], [45, 31], [45, 32], [45, 33], [45, 34], [45, 36], [45, 37], [45, 38], [45, 39], [45, 40], [45, 41], [45, 42], [45, 43], [45, 44], [45, 45], [45, 48], [45, 49], [45, 50], [45, 51], [45, 52], [45, 55], [45, 56], [45, 57], [45, 58], [45, 59], [45, 60], [45, 61], [45, 62], [45, 63], [45, 66], [45, 67], [45, 68], [45, 69], [45, 70], [45, 71], [45, 72], [45, 73], [45, 74], [45, 75], [45, 76], [45, 77], [45, 78], [45, 79], [45, 80], [45, 81], [45, 82], [45, 83], [45, 84], [45, 85], [45, 86], [45, 87], [45, 88], [45, 89], [45, 90], [45, 91], [45, 92], [45, 93], [45, 94], [45, 95], [45, 96], [45, 97], [45, 98], [45, 99], [45, 100], [45, 101], [45, 102], [45, 103], [45, 104], [45, 109], [45, 110], [45, 111], [45, 112], [45, 113], [45, 114], [45, 115], [45, 116], [45, 117], [45, 118], [45, 119], [45, 131], [45, 132], [45, 133], [45, 135], [45, 136], [45, 137], [45, 143], [45, 144], [45, 145], [45, 146], [45, 147], [45, 148], [45, 155], [45, 156], [46, 1], [46, 14], [46, 15], [46, 16], [46, 17], [46, 18], [46, 19], [46, 20], [46, 21], [46, 22], [46, 23], [46, 24], [46, 25], [46, 26], [46, 27], [46, 28], [46, 29], [46, 30], [46, 31], [46, 32], [46, 36], [46, 37], [46, 38], [46, 39], [46, 40], [46, 41], [46, 56], [46, 57], [46, 58], [46, 59], [46, 64], [46, 65], [46, 66], [46, 67], [46, 68], [46, 69], [46, 70], [46, 74], [46, 75], [46, 76], [46, 77], [46, 78], [46, 81], [46, 82], [46, 85], [46, 86], [46, 87], [46, 88], [46, 89], [46, 93], [46, 94], [46, 95], [46, 96], [46, 97], [46, 98], [46, 99], [46, 100], [46, 133], [46, 134], [46, 135], [46, 136], [46, 137], [46, 144], [46, 145], [46, 146], [46, 149], [46, 150], [46, 151], [46, 152], [47, 0], [47, 1], [47, 2], [47, 14], [47, 15], [47, 16], [47, 17], [47, 18], [47, 19], [47, 20], [47, 27], [47, 28], [47, 34], [47, 35], [47, 36], [47, 43], [47, 44], [47, 45], [47, 46], [47, 47], [47, 48], [47, 49], [47, 50], [47, 56], [47, 57], [47, 64], [47, 65], [47, 66], [47, 67], [47, 68], [47, 69], [47, 70], [47, 76], [47, 77], [47, 78], [47, 79], [47, 80], [47, 81], [47, 82], [47, 84], [47, 85], [47, 86], [47, 87], [47, 88], [47, 89], [47, 90], [47, 91], [47, 92], [47, 93], [47, 94], [47, 95], [47, 96], [47, 99], [47, 100], [47, 101], [47, 102], [47, 103], [47, 104], [47, 105], [47, 106], [47, 113], [47, 116], [47, 131], [47, 132], [47, 133], [47, 134], [47, 135], [47, 136], [47, 137], [47, 145], [47, 146], [48, 0], [48, 1], [48, 13], [48, 14], [48, 17], [48, 18], [48, 19], [48, 20], [48, 21], [48, 22], [48, 23], [48, 34], [48, 35], [48, 36], [48, 37], [48, 38], [48, 39], [48, 40], [48, 43], [48, 44], [48, 45], [48, 46], [48, 47], [48, 48], [48, 49], [48, 54], [48, 55], [48, 56], [48, 57], [48, 60], [48, 61], [48, 62], [48, 63], [48, 67], [48, 69], [48, 70], [48, 71], [48, 72], [48, 73], [48, 77], [48, 79], [48, 80], [48, 81], [48, 82], [48, 83], [48, 84], [48, 85], [48, 86], [48, 87], [48, 88], [48, 89], [48, 90], [48, 91], [48, 92], [48, 93], [48, 94], [48, 95], [48, 96], [48, 97], [48, 98], [48, 99], [48, 100], [48, 103], [48, 104], [48, 111], [48, 117], [48, 118], [48, 131], [48, 132], [48, 133], [48, 134], [48, 135], [49, 13], [49, 14], [49, 15], [49, 16], [49, 17], [49, 18], [49, 19], [49, 20], [49, 21], [49, 22], [49, 23], [49, 24], [49, 34], [49, 35], [49, 36], [49, 37], [49, 38], [49, 39], [49, 40], [49, 41], [49, 42], [49, 43], [49, 44], [49, 45], [49, 46], [49, 56], [49, 57], [49, 58], [49, 59], [49, 60], [49, 61], [49, 62], [49, 63], [49, 64], [49, 65], [49, 66], [49, 67], [49, 68], [49, 69], [49, 70], [49, 71], [49, 72], [49, 73], [49, 74], [49, 75], [49, 76], [49, 77], [49, 78], [49, 79], [49, 80], [49, 81], [49, 82], [49, 83], [49, 84], [49, 85], [49, 86], [49, 87], [49, 88], [49, 89], [49, 90], [49, 91], [49, 92], [49, 95], [49, 96], [49, 102], [49, 103], [49, 104], [49, 105], [49, 106], [49, 111], [49, 131], [49, 132], [49, 133], [49, 134], [49, 135], [50, 0], [50, 1], [50, 14], [50, 15], [50, 17], [50, 18], [50, 19], [50, 20], [50, 21], [50, 34], [50, 35], [50, 36], [50, 37], [50, 41], [50, 42], [50, 43], [50, 44], [50, 49], [50, 50], [50, 51], [50, 52], [50, 53], [50, 54], [50, 55], [50, 56], [50, 57], [50, 58], [50, 59], [50, 60], [50, 65], [50, 66], [50, 68], [50, 69], [50, 70], [50, 71], [50, 72], [50, 73], [50, 74], [50, 75], [50, 76], [50, 77], [50, 78], [50, 82], [50, 83], [50, 84], [50, 85], [50, 86], [50, 87], [50, 88], [50, 89], [50, 90], [50, 91], [50, 92], [50, 93], [50, 94], [50, 95], [50, 96], [50, 97], [50, 98], [50, 99], [50, 100], [50, 101], [50, 102], [50, 103], [50, 104], [50, 105], [50, 106], [50, 107], [50, 108], [50, 109], [50, 110], [50, 111], [50, 118], [50, 119], [50, 120], [50, 121], [50, 122], [50, 129], [50, 130], [51, 1], [51, 2], [51, 3], [51, 12], [51, 13], [51, 14], [51, 15], [51, 34], [51, 35], [51, 36], [51, 50], [51, 51], [51, 52], [51, 53], [51, 54], [51, 55], [51, 68], [51, 69], [51, 70], [51, 71], [51, 72], [51, 73], [51, 74], [51, 75], [51, 76], [51, 77], [51, 78], [51, 79], [51, 80], [51, 81], [51, 82], [51, 83], [51, 84], [51, 85], [51, 86], [51, 87], [51, 88], [51, 89], [51, 93], [51, 94], [51, 95], [51, 96], [51, 97], [51, 98], [51, 99], [51, 100], [51, 101], [51, 102], [51, 103], [51, 104], [51, 105], [51, 106], [51, 111], [51, 112], [51, 113], [51, 114], [51, 115], [51, 116], [51, 132], [51, 133], [51, 134], [51, 135], [51, 136], [51, 137], [51, 138], [52, 0], [52, 1], [52, 12], [52, 13], [52, 14], [52, 15], [52, 16], [52, 17], [52, 18], [52, 19], [52, 33], [52, 34], [52, 35], [52, 38], [52, 39], [52, 46], [52, 47], [52, 48], [52, 49], [52, 50], [52, 54], [52, 55], [52, 56], [52, 57], [52, 58], [52, 64], [52, 65], [52, 66], [52, 68], [52, 70], [52, 71], [52, 72], [52, 73], [52, 74], [52, 75], [52, 76], [52, 77], [52, 78], [52, 79], [52, 80], [52, 81], [52, 82], [52, 83], [52, 84], [52, 85], [52, 86], [52, 87], [52, 88], [52, 89], [52, 90], [52, 91], [52, 92], [52, 93], [52, 94], [52, 95], [52, 96], [52, 97], [52, 98], [52, 103], [52, 104], [52, 105], [52, 111], [52, 112], [52, 115], [52, 116], [52, 117], [52, 121], [52, 122], [52, 123], [52, 124], [52, 125], [52, 133], [52, 134], [52, 135], [52, 136], [52, 137], [52, 146], [52, 147], [52, 148], [53, 0], [53, 1], [53, 12], [53, 13], [53, 14], [53, 15], [53, 16], [53, 17], [53, 25], [53, 30], [53, 31], [53, 32], [53, 47], [53, 48], [53, 49], [53, 50], [53, 51], [53, 52], [53, 53], [53, 54], [53, 55], [53, 56], [53, 57], [53, 58], [53, 59], [53, 60], [53, 61], [53, 62], [53, 63], [53, 64], [53, 65], [53, 66], [53, 67], [53, 68], [53, 69], [53, 70], [53, 75], [53, 76], [53, 77], [53, 78], [53, 79], [53, 80], [53, 81], [53, 84], [53, 85], [53, 86], [53, 87], [53, 88], [53, 89], [53, 90], [53, 91], [53, 92], [53, 93], [53, 94], [53, 95], [53, 96], [53, 97], [53, 98], [53, 99], [53, 108], [53, 109], [53, 110], [53, 111], [53, 112], [53, 123], [53, 124], [53, 125], [53, 126], [53, 127], [53, 132], [53, 133], [53, 134], [53, 135], [53, 136], [54, 0], [54, 1], [54, 3], [54, 12], [54, 13], [54, 14], [54, 15], [54, 16], [54, 17], [54, 40], [54, 41], [54, 42], [54, 49], [54, 50], [54, 51], [54, 52], [54, 53], [54, 54], [54, 55], [54, 56], [54, 60], [54, 61], [54, 65], [54, 66], [54, 67], [54, 68], [54, 69], [54, 70], [54, 71], [54, 76], [54, 77], [54, 78], [54, 79], [54, 80], [54, 81], [54, 82], [54, 88], [54, 89], [54, 90], [54, 91], [54, 92], [54, 93], [54, 94], [54, 95], [54, 96], [54, 97], [54, 98], [54, 99], [54, 100], [54, 101], [54, 104], [54, 105], [54, 106], [54, 107], [54, 108], [54, 125], [54, 126], [54, 130], [54, 131], [54, 132], [54, 133], [54, 134], [54, 135], [54, 136], [54, 137], [54, 138], [55, 3], [55, 4], [55, 5], [55, 12], [55, 13], [55, 14], [55, 15], [55, 18], [55, 19], [55, 20], [55, 21], [55, 22], [55, 23], [55, 24], [55, 25], [55, 29], [55, 30], [55, 31], [55, 32], [55, 33], [55, 34], [55, 35], [55, 36], [55, 37], [55, 38], [55, 40], [55, 42], [55, 43], [55, 44], [55, 45], [55, 46], [55, 47], [55, 48], [55, 50], [55, 51], [55, 52], [55, 53], [55, 54], [55, 55], [55, 56], [55, 58], [55, 59], [55, 60], [55, 63], [55, 64], [55, 65], [55, 66], [55, 67], [55, 68], [55, 69], [55, 70], [55, 71], [55, 72], [55, 73], [55, 74], [55, 75], [55, 76], [55, 77], [55, 78], [55, 79], [55, 80], [55, 81], [55, 82], [55, 88], [55, 89], [55, 90], [55, 91], [55, 92], [55, 93], [55, 94], [55, 95], [55, 96], [55, 100], [55, 101], [55, 102], [55, 103], [55, 113], [55, 114], [55, 115], [55, 116], [55, 117], [55, 131], [55, 132], [55, 133], [55, 134], [55, 135], [55, 136], [55, 137], [55, 138], [56, 0], [56, 1], [56, 2], [56, 3], [56, 4], [56, 5], [56, 13], [56, 14], [56, 15], [56, 19], [56, 27], [56, 28], [56, 29], [56, 30], [56, 31], [56, 36], [56, 37], [56, 38], [56, 39], [56, 40], [56, 41], [56, 42], [56, 44], [56, 45], [56, 46], [56, 49], [56, 50], [56, 51], [56, 53], [56, 54], [56, 55], [56, 59], [56, 60], [56, 61], [56, 62], [56, 63], [56, 64], [56, 65], [56, 66], [56, 67], [56, 68], [56, 69], [56, 72], [56, 73], [56, 74], [56, 75], [56, 76], [56, 77], [56, 78], [56, 79], [56, 80], [56, 81], [56, 82], [56, 83], [56, 84], [56, 85], [56, 86], [56, 87], [56, 88], [56, 89], [56, 92], [56, 93], [56, 94], [56, 113], [56, 114], [56, 115], [56, 116], [56, 133], [56, 134], [56, 135], [56, 136], [56, 137], [56, 138], [57, 0], [57, 1], [57, 2], [57, 3], [57, 4], [57, 12], [57, 13], [57, 14], [57, 15], [57, 16], [57, 17], [57, 18], [57, 19], [57, 20], [57, 21], [57, 25], [57, 26], [57, 27], [57, 28], [57, 29], [57, 30], [57, 31], [57, 35], [57, 36], [57, 37], [57, 42], [57, 43], [57, 44], [57, 45], [57, 48], [57, 49], [57, 50], [57, 51], [57, 52], [57, 53], [57, 54], [57, 55], [57, 56], [57, 57], [57, 58], [57, 59], [57, 60], [57, 61], [57, 62], [57, 63], [57, 64], [57, 65], [57, 66], [57, 67], [57, 68], [57, 69], [57, 70], [57, 72], [57, 76], [57, 78], [57, 79], [57, 80], [57, 81], [57, 82], [57, 83], [57, 84], [57, 85], [57, 86], [57, 87], [57, 88], [57, 89], [57, 90], [57, 91], [57, 92], [57, 93], [57, 94], [57, 95], [57, 96], [57, 97], [57, 98], [57, 99], [57, 100], [57, 101], [57, 102], [57, 103], [57, 120], [57, 121], [57, 122], [57, 130], [57, 131], [57, 132], [57, 133], [57, 134], [57, 135], [57, 136], [58, 4], [58, 5], [58, 12], [58, 13], [58, 14], [58, 15], [58, 16], [58, 17], [58, 18], [58, 19], [58, 22], [58, 23], [58, 24], [58, 25], [58, 26], [58, 27], [58, 28], [58, 29], [58, 31], [58, 40], [58, 41], [58, 42], [58, 43], [58, 44], [58, 53], [58, 54], [58, 55], [58, 56], [58, 57], [58, 58], [58, 59], [58, 63], [58, 64], [58, 65], [58, 66], [58, 67], [58, 68], [58, 69], [58, 72], [58, 73], [58, 74], [58, 75], [58, 76], [58, 77], [58, 78], [58, 79], [58, 80], [58, 81], [58, 85], [58, 86], [58, 87], [58, 90], [58, 97], [58, 98], [58, 99], [58, 100], [58, 103], [58, 104], [58, 105], [58, 106], [58, 107], [58, 111], [58, 112], [58, 113], [58, 114], [58, 115], [58, 121], [58, 122], [58, 123], [58, 124], [58, 125], [58, 126], [58, 130], [58, 131], [58, 132], [58, 133], [58, 134], [58, 135], [58, 136], [58, 137], [58, 138], [58, 146], [59, 13], [59, 14], [59, 15], [59, 16], [59, 17], [59, 18], [59, 23], [59, 24], [59, 25], [59, 26], [59, 27], [59, 28], [59, 29], [59, 30], [59, 40], [59, 41], [59, 42], [59, 43], [59, 44], [59, 45], [59, 46], [59, 47], [59, 48], [59, 49], [59, 50], [59, 51], [59, 52], [59, 53], [59, 54], [59, 55], [59, 58], [59, 59], [59, 60], [59, 61], [59, 62], [59, 63], [59, 64], [59, 65], [59, 66], [59, 67], [59, 68], [59, 69], [59, 73], [59, 74], [59, 75], [59, 76], [59, 80], [59, 85], [59, 86], [59, 87], [59, 88], [59, 89], [59, 90], [59, 91], [59, 92], [59, 97], [59, 98], [59, 99], [59, 100], [59, 101], [59, 102], [59, 113], [59, 114], [59, 115], [59, 123], [59, 124], [59, 125], [59, 128], [59, 129], [59, 130], [59, 131], [59, 132], [59, 133], [59, 134], [59, 135], [59, 136], [59, 137], [60, 0], [60, 1], [60, 2], [60, 3], [60, 4], [60, 5], [60, 6], [60, 14], [60, 15], [60, 16], [60, 17], [60, 18], [60, 19], [60, 20], [60, 21], [60, 22], [60, 23], [60, 24], [60, 25], [60, 26], [60, 27], [60, 39], [60, 40], [60, 41], [60, 42], [60, 43], [60, 44], [60, 45], [60, 46], [60, 47], [60, 48], [60, 49], [60, 50], [60, 51], [60, 52], [60, 61], [60, 62], [60, 63], [60, 64], [60, 65], [60, 66], [60, 67], [60, 68], [60, 70], [60, 72], [60, 73], [60, 74], [60, 75], [60, 76], [60, 77], [60, 78], [60, 79], [60, 80], [60, 89], [60, 90], [60, 91], [60, 92], [60, 93], [60, 97], [60, 98], [60, 99], [60, 100], [60, 101], [60, 102], [60, 122], [60, 123], [60, 128], [60, 129], [60, 135], [61, 4], [61, 5], [61, 6], [61, 15], [61, 16], [61, 17], [61, 18], [61, 19], [61, 20], [61, 21], [61, 22], [61, 23], [61, 24], [61, 25], [61, 26], [61, 27], [61, 41], [61, 42], [61, 43], [61, 44], [61, 45], [61, 46], [61, 47], [61, 48], [61, 49], [61, 50], [61, 51], [61, 55], [61, 56], [61, 60], [61, 61], [61, 62], [61, 63], [61, 70], [61, 71], [61, 75], [61, 76], [61, 77], [61, 78], [61, 79], [61, 80], [61, 81], [61, 82], [61, 83], [61, 92], [61, 93], [61, 94], [61, 102], [61, 103], [61, 104], [61, 105], [61, 106], [61, 107], [61, 108], [62, 4], [62, 5], [62, 6], [62, 16], [62, 17], [62, 18], [62, 19], [62, 20], [62, 21], [62, 22], [62, 23], [62, 24], [62, 25], [62, 26], [62, 27], [62, 48], [62, 49], [62, 50], [62, 54], [62, 55], [62, 58], [62, 59], [62, 60], [62, 61], [62, 75], [62, 76], [62, 77], [62, 78], [62, 98], [62, 99], [62, 103], [62, 104], [62, 105], [62, 118], [62, 119], [62, 120], [63, 0], [63, 1], [63, 2], [63, 3], [63, 4], [63, 5], [63, 6], [63, 7], [63, 16], [63, 17], [63, 18], [63, 19], [63, 20], [63, 21], [63, 22], [63, 23], [63, 24], [63, 25], [63, 26], [63, 41], [63, 42], [63, 53], [63, 54], [63, 55], [63, 56], [63, 57], [63, 58], [63, 60], [63, 61], [63, 62], [63, 63], [63, 64], [63, 65], [63, 68], [63, 69], [63, 70], [63, 71], [63, 72], [63, 73], [63, 74], [63, 81], [63, 82], [63, 83], [63, 84], [63, 85], [63, 86], [63, 88], [63, 89], [63, 93], [63, 94], [63, 99], [63, 100], [63, 101], [63, 102], [63, 103], [63, 104], [63, 105], [63, 106], [63, 107], [63, 108], [63, 132], [63, 133], [63, 135], [64, 0], [64, 1], [64, 2], [64, 3], [64, 4], [64, 5], [64, 6], [64, 7], [64, 17], [64, 18], [64, 19], [64, 20], [64, 21], [64, 22], [64, 23], [64, 24], [64, 25], [64, 44], [64, 45], [64, 46], [64, 47], [64, 48], [64, 49], [64, 50], [64, 51], [64, 52], [64, 53], [64, 54], [64, 55], [64, 56], [64, 60], [64, 61], [64, 62], [64, 63], [64, 65], [64, 67], [64, 69], [64, 70], [64, 71], [64, 72], [64, 73], [64, 74], [64, 78], [64, 79], [64, 80], [64, 81], [64, 82], [64, 94], [64, 95], [64, 96], [64, 98], [64, 99], [64, 100], [64, 101], [64, 102], [64, 106], [64, 107], [64, 108], [64, 109], [64, 113], [64, 114], [64, 115], [64, 131], [64, 132], [64, 135], [64, 136], [64, 137], [64, 138], [65, 0], [65, 1], [65, 2], [65, 3], [65, 4], [65, 5], [65, 6], [65, 7], [65, 18], [65, 19], [65, 20], [65, 21], [65, 22], [65, 23], [65, 41], [65, 42], [65, 43], [65, 44], [65, 45], [65, 49], [65, 50], [65, 51], [65, 52], [65, 53], [65, 54], [65, 55], [65, 60], [65, 61], [65, 62], [65, 63], [65, 64], [65, 65], [65, 66], [65, 67], [65, 71], [65, 72], [65, 73], [65, 78], [65, 79], [65, 80], [65, 81], [65, 82], [65, 83], [65, 84], [65, 102], [65, 103], [65, 104], [65, 105], [65, 106], [65, 107], [65, 111], [65, 112], [65, 113], [65, 114], [65, 115], [65, 130], [65, 131], [65, 132], [65, 133], [65, 134], [65, 136], [65, 137], [66, 6], [66, 7], [66, 18], [66, 19], [66, 20], [66, 21], [66, 22], [66, 23], [66, 49], [66, 50], [66, 51], [66, 52], [66, 53], [66, 54], [66, 55], [66, 60], [66, 61], [66, 62], [66, 63], [66, 64], [66, 65], [66, 67], [66, 92], [66, 93], [66, 94], [66, 95], [66, 96], [66, 104], [66, 106], [66, 107], [66, 108], [66, 111], [66, 112], [66, 113], [66, 114], [66, 133], [66, 134], [66, 135], [66, 136], [66, 137], [66, 138], [66, 139], [67, 0], [67, 1], [67, 2], [67, 3], [67, 4], [67, 5], [67, 6], [67, 7], [67, 20], [67, 21], [67, 22], [67, 23], [67, 39], [67, 40], [67, 45], [67, 46], [67, 47], [67, 48], [67, 49], [67, 50], [67, 51], [67, 52], [67, 53], [67, 54], [67, 55], [67, 56], [67, 57], [67, 61], [67, 62], [67, 63], [67, 64], [67, 65], [67, 66], [67, 77], [67, 78], [67, 79], [67, 80], [67, 81], [67, 82], [67, 83], [67, 91], [67, 99], [67, 100], [67, 101], [67, 102], [67, 103], [67, 104], [67, 105], [67, 106], [67, 107], [67, 122], [67, 123], [67, 135], [67, 136], [67, 137], [67, 138], [67, 139], [68, 0], [68, 1], [68, 3], [68, 4], [68, 5], [68, 6], [68, 7], [68, 20], [68, 21], [68, 22], [68, 38], [68, 39], [68, 40], [68, 41], [68, 42], [68, 47], [68, 48], [68, 51], [68, 52], [68, 53], [68, 65], [68, 66], [68, 67], [68, 68], [68, 72], [68, 73], [68, 74], [68, 75], [68, 76], [68, 81], [68, 82], [68, 83], [68, 84], [68, 85], [68, 86], [68, 88], [68, 89], [68, 90], [68, 91], [68, 92], [68, 93], [68, 94], [68, 105], [68, 106], [68, 107], [68, 109], [68, 110], [68, 111], [68, 112], [68, 135], [68, 136], [68, 137], [69, 1], [69, 2], [69, 3], [69, 4], [69, 5], [69, 6], [69, 7], [69, 8], [69, 9], [69, 21], [69, 22], [69, 31], [69, 32], [69, 46], [69, 47], [69, 51], [69, 52], [69, 53], [69, 60], [69, 72], [69, 73], [69, 74], [69, 75], [69, 76], [69, 77], [69, 78], [69, 79], [69, 80], [69, 81], [69, 82], [69, 83], [69, 92], [69, 106], [69, 107], [70, 2], [70, 3], [70, 4], [70, 5], [70, 6], [70, 7], [70, 8], [70, 29], [70, 30], [70, 52], [70, 53], [70, 54], [70, 55], [70, 56], [70, 57], [70, 58], [70, 60], [70, 61], [70, 62], [70, 72], [70, 73], [70, 76], [70, 77], [70, 83], [70, 84], [70, 102], [70, 103], [70, 104], [70, 105], [70, 106], [70, 107], [70, 108], [70, 112], [70, 113], [70, 124], [70, 125], [71, 1], [71, 2], [71, 3], [71, 4], [71, 5], [71, 6], [71, 7], [71, 8], [71, 20], [71, 21], [71, 22], [71, 50], [71, 51], [71, 54], [71, 55], [71, 61], [71, 75], [71, 76], [71, 77], [71, 99], [71, 100], [71, 104], [71, 105], [71, 106], [71, 107], [71, 108], [71, 109], [71, 110], [71, 111], [72, 0], [72, 1], [72, 2], [72, 3], [72, 4], [72, 5], [72, 6], [72, 7], [72, 24], [72, 25], [72, 60], [72, 61], [72, 62], [72, 63], [72, 72], [72, 73], [72, 74], [72, 75], [72, 129], [73, 0], [73, 1], [73, 2], [73, 3], [73, 4], [73, 5], [73, 6], [73, 7], [73, 28], [73, 29], [73, 30], [73, 47], [73, 72], [73, 73], [73, 74], [73, 81], [73, 82], [73, 83], [73, 89], [73, 90], [73, 100], [73, 101], [73, 102], [73, 105], [73, 106], [73, 147], [73, 148], [74, 0], [74, 1], [74, 2], [74, 3], [74, 4], [74, 5], [74, 6], [74, 27], [74, 28], [74, 29], [74, 30], [74, 43], [74, 44], [74, 45], [74, 46], [74, 47], [74, 48], [74, 51], [74, 52], [74, 59], [74, 60], [74, 61], [74, 62], [74, 63], [74, 64], [74, 65], [74, 66], [74, 67], [74, 68], [74, 69], [74, 70], [74, 71], [74, 72], [74, 74], [74, 84], [74, 85], [74, 90], [74, 91], [74, 92], [74, 93], [74, 111], [75, 0], [75, 1], [75, 5], [75, 6], [75, 26], [75, 27], [75, 28], [75, 43], [75, 44], [75, 45], [75, 51], [75, 52], [75, 59], [75, 60], [75, 61], [75, 62], [75, 63], [75, 64], [75, 65], [75, 66], [75, 67], [75, 68], [75, 69], [75, 70], [75, 71], [75, 72], [75, 73], [75, 74], [76, 0], [76, 1], [76, 2], [76, 3], [76, 4], [76, 5], [76, 6], [76, 24], [76, 25], [76, 28], [76, 29], [76, 30], [76, 35], [76, 36], [76, 37], [76, 50], [76, 51], [76, 57], [76, 58], [76, 59], [76, 60], [76, 65], [76, 66], [76, 67], [76, 68], [76, 69], [76, 88], [76, 89], [76, 90], [77, 0], [77, 1], [77, 2], [77, 3], [77, 4], [77, 24], [77, 25], [77, 26], [77, 27], [77, 28], [77, 41], [77, 47], [77, 48], [77, 57], [77, 58], [77, 59], [78, 1], [78, 17], [78, 18], [78, 19], [78, 20], [78, 21], [78, 22], [78, 27], [78, 28], [78, 29], [78, 30], [78, 31], [78, 32], [78, 36], [78, 48], [78, 57], [78, 58], [78, 59], [78, 147], [78, 148], [79, 0], [79, 1], [79, 2], [79, 5], [79, 6], [79, 7], [79, 10], [79, 11], [79, 12], [79, 16], [79, 17], [79, 18], [79, 19], [79, 29], [79, 30], [79, 31], [79, 35], [79, 36], [79, 37], [79, 42], [79, 43], [79, 46], [79, 47], [79, 48], [79, 49], [79, 56], [79, 57], [79, 58], [79, 59], [79, 70], [79, 71], [79, 72], [79, 73], [79, 74], [80, 16], [80, 17], [80, 18], [80, 30], [80, 31], [80, 39], [80, 40], [80, 41], [80, 42], [80, 43], [80, 44], [80, 45], [80, 46], [80, 48], [80, 55], [80, 56], [80, 57], [80, 58], [80, 59], [80, 60], [80, 63], [80, 64], [80, 77], [80, 140], [80, 141], [80, 142], [81, 0], [81, 1], [81, 2], [81, 6], [81, 8], [81, 9], [81, 10], [81, 11], [81, 18], [81, 19], [81, 37], [81, 38], [81, 39], [81, 42], [81, 43], [81, 44], [81, 45], [81, 46], [81, 57], [81, 58], [81, 59], [81, 63], [81, 77], [81, 78], [82, 0], [82, 1], [82, 2], [82, 3], [82, 4], [82, 5], [82, 6], [82, 7], [82, 8], [82, 9], [82, 14], [82, 15], [82, 16], [82, 17], [82, 18], [82, 19], [82, 43], [82, 44], [82, 45], [82, 46], [82, 47], [82, 48], [82, 49], [82, 50], [82, 51], [82, 55], [82, 56], [82, 57], [82, 141], [83, 0], [83, 1], [83, 2], [83, 3], [83, 4], [83, 5], [83, 6], [83, 10], [83, 12], [83, 42], [83, 43], [83, 47], [83, 48], [83, 49], [83, 50], [83, 71], [83, 72], [83, 76], [83, 77], [83, 78], [83, 79], [83, 80], [83, 81], [84, 1], [84, 2], [84, 3], [84, 4], [84, 5], [84, 6], [84, 7], [84, 13], [84, 14], [84, 15], [84, 16], [84, 17], [84, 18], [84, 30], [84, 32], [84, 33], [84, 34], [84, 35], [84, 36], [84, 37], [84, 45], [84, 46], [84, 47], [84, 51], [84, 52], [84, 53], [84, 61], [84, 63], [84, 64], [84, 65], [84, 74], [84, 75], [84, 78], [84, 79], [84, 81], [84, 82], [84, 150], [84, 151], [85, 0], [85, 1], [85, 2], [85, 3], [85, 5], [85, 6], [85, 9], [85, 10], [85, 32], [85, 33], [85, 47], [85, 48], [85, 49], [85, 50], [85, 66], [85, 67], [85, 68], [85, 69], [85, 80], [85, 81], [85, 101], [85, 139], [85, 140], [85, 150], [86, 13], [86, 14], [86, 15], [86, 18], [86, 19], [86, 20], [86, 50], [86, 51], [86, 53], [86, 54], [86, 60], [86, 61], [86, 80], [86, 81], [87, 13], [87, 14], [87, 60], [87, 61], [87, 62], [87, 66], [87, 67], [87, 68], [87, 69], [87, 81], [87, 82], [88, 65], [88, 66], [88, 67], [88, 68], [88, 136], [88, 137], [88, 138], [88, 139], [89, 1], [89, 2], [89, 9], [89, 10], [89, 14], [89, 42], [89, 43], [89, 83], [89, 84], [90, 0], [90, 1], [90, 42], [90, 43], [90, 85], [91, 42], [91, 43], [91, 84], [91, 85], [92, 24], [92, 25], [92, 32], [92, 33], [92, 41], [92, 42], [92, 43], [92, 44], [93, 132], [93, 133], [93, 134], [93, 135], [93, 136], [94, 5], [94, 6], [94, 17], [94, 18], [95, 102], [95, 103], [95, 119], [95, 120], [95, 121], [96, 1], [96, 51], [96, 110], [96, 111], [96, 123], [96, 124], [97, 0], [97, 1], [97, 28], [97, 29], [97, 30], [97, 43], [97, 45], [97, 46], [97, 47], [97, 48], [97, 50], [97, 51], [97, 52], [97, 113], [97, 114], [97, 121], [97, 122], [97, 123], [98, 0], [98, 1], [98, 126], [99, 0], [99, 1], [99, 43], [99, 44], [100, 59], [100, 65], [100, 66], [101, 0], [101, 1], [101, 2], [103, 64], [104, 55], [113, 4], [113, 5]]
InĀ [46]:
#f1_ssvae_2_labels.tolist().index([ 101, 90])
InĀ [47]:
#plt.scatter(f1_ssvae_3_labels[:,1], f1_ssvae_3_labels[:,0], s=1, cmap='Viridis')

Label plot¶

InĀ [56]:
# this plot shows the first 180 spectra the SSVAE model assigns to a specified class
ssvae_label_plot(f1_img2, f1_ssvae_2_labels, f1_wav) # Spectra from class 3
No description has been provided for this image

Plotting Results¶

Plot code¶

SSVAE Grain 1 Plot¶

The first image in the figure below is a plot of the latent space color mapped according to the four spectral feature classes defined above. The second image is the hybrid perovskite cell showing the spatial locations of the four classes.

InĀ [76]:
# SSVAE with 40 supervised data points
ssvae_plot("SSVAE Grain 1", f1_ssvae_z_mean, f1_ssvae_z_labels, f1_xpix, f1_ypix, 50)
No description has been provided for this image

Spectral label plot¶

InĀ [85]:
# Plot one spectrum from each class in the labeled data
spect_label_plot("Spectral Classes", f1_img2, f1_pts, f1_wav)
No description has been provided for this image

Determining latent dimensions¶

InĀ [97]:
# X-axis
f1_ssvae_z_mean_x = f1_ssvae_z_mean[:,0].detach().cpu().numpy()
f1_ssvae_z_mean_x = f1_ssvae_z_mean_x.reshape(f1_ypix, f1_xpix)
print("X Min: ", (f1_ssvae_z_mean_x==np.min(f1_ssvae_z_mean_x)).nonzero())
print("X Max: ", (f1_ssvae_z_mean_x==np.max(f1_ssvae_z_mean_x)).nonzero())
f1_ssvae_z_mean_x_sort = np.dstack(
    np.unravel_index(np.argsort(f1_ssvae_z_mean_x.ravel()), (f1_ypix, f1_xpix)))
f1_ssvae_z_mean_x_sort = np.squeeze(f1_ssvae_z_mean_x_sort)

spectra_plot("SSVAE Grain 1 X-Axis", f1_img2, f1_ssvae_z_mean_x_sort, f1_xpix, f1_ypix, f1_wav)
X Min:  (array([13]), array([53]))
X Max:  (array([121]), array([146]))
No description has been provided for this image
InĀ [98]:
# Y-axis
f1_ssvae_z_mean_y = f1_ssvae_z_mean[:,1].detach().cpu().numpy()
f1_ssvae_z_mean_y = f1_ssvae_z_mean_y.reshape(f1_ypix, f1_xpix)
print("Y Min: ", (f1_ssvae_z_mean_y==np.min(f1_ssvae_z_mean_y)).nonzero())
print("Y Max: ", (f1_ssvae_z_mean_y==np.max(f1_ssvae_z_mean_y)).nonzero())
f1_ssvae_z_mean_y_sort = np.dstack(
    np.unravel_index(np.argsort(f1_ssvae_z_mean_y.ravel()), (f1_ypix, f1_xpix)))
f1_ssvae_z_mean_y_sort = np.squeeze(f1_ssvae_z_mean_y_sort)
spectra_plot("SSVAE Grain 1 Y-Axis", f1_img2, f1_ssvae_z_mean_y_sort, f1_xpix, f1_ypix, f1_wav)
Y Min:  (array([114]), array([137]))
Y Max:  (array([36]), array([18]))
No description has been provided for this image

Grain 2 on SSVAE Model 1¶

InĀ [99]:
f2on1_ssvae_z_mean, f2on1_ssvae_z_sd, f2on1_ssvae_z_labels = f1_ssvae.encode(f2_train_data)
f2on1_ssvae_z_mean = normalize(f2on1_ssvae_z_mean)
f1_ssvae_z_sd_6 = normalize(f1_ssvae_z_sd)

f2on1_ssvae_z_mean, f2on1_ssvae_z_sd, f2on1_ssvae_z_labels = f1_ssvae.encode(f2_train_data)
f2on1_ssvae_z_mean = normalize(f2on1_ssvae_z_mean)
f2on1_ssvae_z_sd = normalize(f2on1_ssvae_z_sd)

f2on1_ssvae_z_labels_2d = f2on1_ssvae_z_labels.reshape(f2_ypix,f2_xpix)
f2on1_ssvae_0_labels = (f2on1_ssvae_z_labels_2d == 0).nonzero(as_tuple=False)
f2on1_ssvae_1_labels = (f2on1_ssvae_z_labels_2d == 1).nonzero(as_tuple=False)
f2on1_ssvae_2_labels = (f2on1_ssvae_z_labels_2d == 2).nonzero(as_tuple=False)
f2on1_ssvae_3_labels = (f2on1_ssvae_z_labels_2d == 3).nonzero(as_tuple=False)
InĀ [100]:
ssvae_plot("SSVAE Grain 2 on Grain 1 Model", f2on1_ssvae_z_mean, f2on1_ssvae_z_labels, 
           f2_xpix, f2_ypix, 33.333333333)
No description has been provided for this image
InĀ [Ā ]:
ssvae_label_plot(f2_img2, f2on1_ssvae_2_labels, f2_wav, 180)
InĀ [111]:
custom_spect_labels_2on1 = [f2on1_ssvae_0_labels[0], f2on1_ssvae_1_labels[128], 
                            f2on1_ssvae_2_labels[11], f2on1_ssvae_3_labels[161]]

# Plot one spectrum from each class in the latent representation of the data
custom_spect_label_plot("Classes from Grain 2 on Model 1", f2_img2, custom_spect_labels_2on1, f2_wav)
No description has been provided for this image
InĀ [109]:
#f1_decode = f1_ssvae.decode(f1_ssvae_z_mean[0], f1_ssvae_z_labels)